使用XSLT在节点计数时转换带有条件的XML
我正在尝试从XML文件中删除节点。对于每个XML只使用一个XSLT,我需要根据文档元素的子元素数量在XSLT中做出决策使用XSLT在节点计数时转换带有条件的XML,xml,xslt,Xml,Xslt,我正在尝试从XML文件中删除节点。对于每个XML只使用一个XSLT,我需要根据文档元素的子元素数量在XSLT中做出决策 <root> <branch> <foo>bar</foo> </branch> <root> 酒吧 应该转化为 <branch> </branch> 但是 酒吧 巴兹 进入 也就是说,如果根元素的(唯一)子元素在应用XSLT后可以充当结果
<root>
<branch>
<foo>bar</foo>
</branch>
<root>
酒吧
应该转化为
<branch>
</branch>
但是
酒吧
巴兹
进入
也就是说,如果根元素的(唯一)子元素在应用XSLT后可以充当结果XML的新文档根,则应该删除根元素。每次都必须删除
节点
有没有办法用单个XSL执行此操作?试试看
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root[*[2]]">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="root[* and not(*[2])]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="branch/foo"/>
一种更简单、更短、更通用(无元素名称硬编码)的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*[not(*[2])]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/*/*/node()"/>
</xsl:stylesheet>
<branch></branch>
<root>
<branch></branch>
<branch></branch>
</root>
<t>
<b></b>
<b></b>
</t>
<t>
<b>
<f>brrr</f>
</b>
<b>
<f>bzzz</f>
</b>
</t>
当此转换应用于第一个提供的XML文档时(更正为格式正确):
酒吧
生成所需的正确结果:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*[not(*[2])]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/*/*/node()"/>
</xsl:stylesheet>
<branch></branch>
<root>
<branch></branch>
<branch></branch>
</root>
<t>
<b></b>
<b></b>
</t>
<t>
<b>
<f>brrr</f>
</b>
<b>
<f>bzzz</f>
</b>
</t>
在第二个提供的XML文档上应用相同的转换时(同样需要更正格式是否正确):
酒吧
巴兹
再次生成所需的正确输出:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*[not(*[2])]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/*/*/node()"/>
</xsl:stylesheet>
<branch></branch>
<root>
<branch></branch>
<branch></branch>
</root>
<t>
<b></b>
<b></b>
</t>
<t>
<b>
<f>brrr</f>
</b>
<b>
<f>bzzz</f>
</b>
</t>
说明:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*[not(*[2])]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/*/*/node()"/>
</xsl:stylesheet>
<branch></branch>
<root>
<branch></branch>
<branch></branch>
</root>
<t>
<b></b>
<b></b>
</t>
<t>
<b>
<f>brrr</f>
</b>
<b>
<f>bzzz</f>
</b>
</t>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*[not(*[2])]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/*/*/node()"/>
</xsl:stylesheet>
<branch></branch>
<root>
<branch></branch>
<branch></branch>
</root>
<t>
<b></b>
<b></b>
</t>
<t>
<b>
<f>brrr</f>
</b>
<b>
<f>bzzz</f>
</b>
</t>
这种转换可以应用于任何XML文档,而不管其中的元素名称如何,并且仍然可以生成所需的正确结果
例如,当应用于此XML文档时:
<t>
<b>
<f>brrr</f>
</b>
<b>
<f>bzzz</f>
</b>
</t>
brrr
bzzz
生成所需的正确结果:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*[not(*[2])]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/*/*/node()"/>
</xsl:stylesheet>
<branch></branch>
<root>
<branch></branch>
<branch></branch>
</root>
<t>
<b></b>
<b></b>
</t>
<t>
<b>
<f>brrr</f>
</b>
<b>
<f>bzzz</f>
</b>
</t>
将此结果与当前公认答案产生的结果进行对比:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*[not(*[2])]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/*/*/node()"/>
</xsl:stylesheet>
<branch></branch>
<root>
<branch></branch>
<branch></branch>
</root>
<t>
<b></b>
<b></b>
</t>
<t>
<b>
<f>brrr</f>
</b>
<b>
<f>bzzz</f>
</b>
</t>
brrr
bzzz
+1谢谢,似乎在我的沙箱中工作。我现在正在学习XSLT:像[*而不是…]这样的正则表达式是否需要XSLT2.0?用于字符串匹配的正则表达式仅在XSLT和XPath2.0中受支持。但是,我只使用了XSLT1.0元素匹配模式,因为match=“root[*[2]]”
只是match=“root[child::*[2]]”
的缩写形式,意思是将root
元素与至少两个任意名称的子元素进行匹配。