使用xslt转换嵌套的xml项
如何使用xslt转换嵌套的XML元素,保持结构不变 假设我有这样一个XML文档:使用xslt转换嵌套的xml项,xml,xslt,Xml,Xslt,如何使用xslt转换嵌套的XML元素,保持结构不变 假设我有这样一个XML文档: <?xml version="1.0" encoding="UTF-8"?> <root> <node> </node> <node> <node> <node> </node> </node> </node> </root>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<node>
</node>
<node>
<node>
<node>
</node>
</node>
</node>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<element>
</element>
<element>
<element>
<element>
</element>
</element>
</element>
</root>
我想得到这样的东西:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<node>
</node>
<node>
<node>
<node>
</node>
</node>
</node>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<element>
</element>
<element>
<element>
<element>
</element>
</element>
</element>
</root>
我应该使用哪种xslt
谢谢
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
<root>
<xsl:apply-templates />
</root>
</xsl:template>
<xsl:template match="node">
<element>
<xsl:apply-templates />
</element>
</xsl:template>
</xsl:stylesheet>
关键是
apply templates
标记以递归方式处理标记内容。在XSLT中实现这一点的方法是(使用and push样式):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node">
<element>
<xsl:apply-templates select="node()|@*"/>
</element>
</xsl:template>
</xsl:stylesheet>
<root>
<node>
</node>
<node>
<node>
<node>
</node>
</node>
</node>
</root>
<root>
<element/>
<element>
<element>
<element/>
</element>
</element>
</root>
当此转换应用于提供的XML文档时:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node">
<element>
<xsl:apply-templates select="node()|@*"/>
</element>
</xsl:template>
</xsl:stylesheet>
<root>
<node>
</node>
<node>
<node>
<node>
</node>
</node>
</node>
</root>
<root>
<element/>
<element>
<element>
<element/>
</element>
</element>
</root>
生成所需的正确结果:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node">
<element>
<xsl:apply-templates select="node()|@*"/>
</element>
</xsl:template>
</xsl:stylesheet>
<root>
<node>
</node>
<node>
<node>
<node>
</node>
</node>
</node>
</root>
<root>
<element/>
<element>
<element>
<element/>
</element>
</element>
</root>
注意事项:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node">
<element>
<xsl:apply-templates select="node()|@*"/>
</element>
</xsl:template>
</xsl:stylesheet>
<root>
<node>
</node>
<node>
<node>
<node>
</node>
</node>
</node>
</root>
<root>
<element/>
<element>
<element>
<element/>
</element>
</element>
</root>
“什么样的”?这到底意味着什么?第二个示例不是有效的XML,因为有两个根元素。在一个有效的XML文档中只能有一个根元素。@Ignacio:我的意思是你能帮我写一个xslt,它可以使用示例XML吗@奥德:你说得对,我修正了。问得好,+1。请参阅我的答案,了解使用标识规则和纯推送样式的最“符合XSLT精神”的经典解决方案回答得好。您可能有兴趣了解身份规则设计模式——请参阅我的答案。我知道这是一个较旧的答案,但我很好奇:
模板为什么指定节点()|@*
作为
的选择器?据我所知,一个直接的
完成了同样的事情(因为标识模板已经指定了选择器)。@ABach:Identity规则的功能是不用修改就使用它——在这种特殊情况下,没有属性,但是明天有人可以更改XML文档的格式并添加一些属性。如果你坚持精确的身份规则,你就不必改变一个字符——所有的事情都会按预期的方式继续工作。啊,我明白了,我没想到在那个级别使用<代码> <代码>不会捕获子/孙子/等节点中的属性。谢谢你,迪米特里@阿巴克:不客气。您可以在此处阅读有关标识规则的更多信息: