我目前正在尝试将XML文件转换为多个输出XML文件,方法是获取它的某些元素并遍历所选元素的祖先。
例如:
源XML:
<?xml version="1.0" encoding="utf-8"?>
<root>
<level_a>
<level_b>
<level_c>
<level_d>
<level_e/>
</level_d>
</level_c>
</level_b>
<level_b>
<level_c>
<level_d>
<level_e/>
</level_d>
</level_c>
</level_b>
<level_b>
<level_c>
<level_d>
<level_e/>
<level_e/>
<level_e/>
</level_d>
</level_c>
</level_b>
<level_b>
<level_c>
<level_d>
<level_d>
<level_e/>
</level_d>
</level_d>
</level_c>
</level_b>
</level_a>
</root>
输出XML文件:
1:
<output>
<output level="b">
<output level="c">
<output level="d">
<output level="e"/>
</output>
</output>
</output>
</output>
2:
<output>
<output level="b">
<output level="c">
<output level="d">
<output level="e"/>
</output>
</output>
</output>
</output>
3:
<output>
<output level="b">
<output level="c">
<output level="d">
<output level="e"/>
<output level="e"/>
<output level="e"/>
</output>
</output>
</output>
</output>
4:
<output>
<output level="b">
<output level="c">
<output level="d">
<output level="d">
<output level="e"/>
</output>
</output>
</output>
</output>
</output>
我知道我可以在使用以下XPath生成序列的过程中做一些事情:
(// level_d [否(level_d)])[最后一个()] /祖先:: * [自:: level_c |自:: level_b]
然后使用foreach迭代它,我将按文档顺序获取结果。
但我真正感兴趣的是如何在不使用foreach的情况下实现同样的目标,我能想到的任何解决方案都会使所有元素都反转...
非常感谢任何提示
最诚挚的问候
明经
答案 0 :(得分:3)
不确定为什么你会自下而上而不是自上而下。我会匹配/*/*
并在那里创建结果文档。
示例...
XML输入
<root>
<level_a>
<level_b>
<level_c>
<level_d>
<level_e/>
</level_d>
</level_c>
</level_b>
</level_a>
<level_b>
<level_c>
<level_d>
<level_d>
<level_e/>
</level_d>
</level_d>
</level_c>
</level_b>
</root>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template name="output">
<output level="{substring-after(name(),'level_')}">
<xsl:apply-templates/>
</output>
</xsl:template>
<xsl:template match="/*/*" priority="1">
<xsl:result-document href="{generate-id()}.xml">
<output>
<xsl:call-template name="output"/>
</output>
</xsl:result-document>
</xsl:template>
<xsl:template match="*[starts-with(name(),'level_')]">
<xsl:call-template name="output"/>
</xsl:template>
</xsl:stylesheet>
文件1 (由于generate-id()
)
<output>
<output level="a">
<output level="b">
<output level="c">
<output level="d">
<output level="e"/>
</output>
</output>
</output>
</output>
</output>
文件2 (由于generate-id()
)
<output>
<output level="b">
<output level="c">
<output level="d">
<output level="d">
<output level="e"/>
</output>
</output>
</output>
</output>
</output>
答案 1 :(得分:0)
作为变量解决方案,如果level_a或level_d发生变化,您可以在此处调整值:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="//level_d[not(ancestor::level_d)]">
<xsl:result-document href="{concat('file_', count(preceding::*[self::level_d])+1,'.xml')}">
<output>
<xsl:apply-templates select="ancestor-or-self::node()[parent::level_a]" mode="output"></xsl:apply-templates>
</output>
</xsl:result-document>
</xsl:template>
<xsl:template match="*" mode="output">
<output level="{substring-after(local-name(),'level_')}">
<xsl:apply-templates mode="output"/>
</output>
</xsl:template>
</xsl:stylesheet>
它与预期的结果相同。