使用 XSLT 作为 XML 预处理器
这是我第一次使用 XSLT 或 XML 做任何事情,所以请原谅。我发现 XSLT Web 文档非常简洁。
我有一个 XML 文件,我想要对其进行处理,以根据输入的定义集有选择地删除内容。该行为应该类似于处理 ifdef 块的简单代码预处理器。
我已经弄清楚了如何做到这一点,如下所示,但某些部分(例如“内容”变量)似乎不是处理此问题的最佳方法。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:param name="defines-uri" required="yes"/>
<xsl:template match="* | @*">
<xsl:copy><xsl:copy-of select="@*"/><xsl:apply-templates/></xsl:copy>
</xsl:template>
<xsl:template match="ifdef">
<xsl:variable name="contents" select="child::node()"/>
<xsl:variable name="defines" select="document($defines-uri)/defines"/>
<xsl:variable name="val" select="@select"/>
<xsl:for-each select="$defines">
<xsl:if test="def=$val">
<xsl:apply-templates select="$contents"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
主要问题是在定义中找到匹配项时应用模板的情况。如果没有内容,我会在输出中不同程度地转储定义文档。
在不进行转换的情况下对 XML 进行预处理的最佳方法是什么?
This is my first time doing anything with XSLT, or XML really, so please excuse me. I've found XSLT web documentation is really terse.
I have an XML file that I want to process to selectively drop content based on an input set of defines. The behavior should be similar to a simple code pre-processor handling ifdef blocks.
I've worked out how to do it as below, but some parts such as the "contents" variable didn't seem like the best way to handle this.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:param name="defines-uri" required="yes"/>
<xsl:template match="* | @*">
<xsl:copy><xsl:copy-of select="@*"/><xsl:apply-templates/></xsl:copy>
</xsl:template>
<xsl:template match="ifdef">
<xsl:variable name="contents" select="child::node()"/>
<xsl:variable name="defines" select="document($defines-uri)/defines"/>
<xsl:variable name="val" select="@select"/>
<xsl:for-each select="$defines">
<xsl:if test="def=$val">
<xsl:apply-templates select="$contents"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
The main issue was the apply-templates on the case when a match was found in the defines. Without the contents, I get the defines document dumped to different degrees in the output.
Whats the best way to do pre-processing of XML without transformation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
嗯,基本上你是对的。不过,您仍然可以对其进行一些改进:
更改上下文节点。在其中,.
指的是正在迭代的节点,而不是由
匹配的节点。这意味着您必须在变量中保留“外部”上下文,这是标准做法。
Well, basically you got it right. You can still improve it a little, though:
The
<xsl:for-each>
changes the context node. Within it, the.
refers to the node being iterated over, not the one that had been matched by the<xsl:template>
.That means you have to preseve the "outer" context in a variable, this is standard practice.
对于刚刚开始使用 XSLT 和 XML 的人来说,您做得非常好。
这不是您问题的答案,但我只是想说这可能是一个更安全的“默认复制”模板:
您的模板可以通过某个默认内置模板的恩典来工作。但是,当您添加更多模板时,您可能会遇到有关文本节点(或其他非元素的东西)的奇怪行为,因为默认值的优先级较低。
You're doing really well for someone who's only just beginning with XSLT and XML.
This isn't an answer to your question, but I just wanted to say that this might be a safer "copy by default" template:
Yours works by grace of a certain default built-in template. But you might get strange behaviour regarding text nodes (or other things that aren't elements) when you add more templates, since the default has a low priority.