我需要转换成这样的平面结构
<root>
<H>1</H>
<I>1-1</I>
<I>1-2</I>
<I>1-3</I>
<H>2</H>
<I>2-1</I>
<I>2-2</I>
</root>在一个像这样的
<root>
<H>
1
<I>1-1</I>
<I>1-2</I>
<I>1-3</I>
</H>
<H>
2
<I>2-1</I>
<I>2-2</I>
</H>
</root>我用这种方式尝试了源结构上的每一种方法
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="root">
<root>
<xsl:for-each select="child::node()">
<xsl:if test="self::H">
<H>
<xsl:copy-of select="@* | node()"/>
<xsl:call-template name="copyI"/>
</H>
</xsl:if>
</xsl:for-each>
</root>
</xsl:template>
<xsl:template name="copyI">
<xsl:for-each select="following-sibling::node()">
<xsl:choose>
<xsl:when test="self::H">
<!-- Should be fantastic to exit from the loop! -->
</xsl:when>
<xsl:when test="self::I"
<I>
<xsl:copy-of select="@* | node()"/>
</I>
<xsl:text> </xsl:text>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>不幸的是,我能达到的最好的结果就是
<root>
<H>
1
<I>1-1</I>
<I>1-2</I>
<I>1-3</I>
<I>2-1</I> wrong!
<I>2-2</I> wrong!
</H>
<H>
2
<I>2-1</I>
<I>2-2</I>
</H>
</root><I>2-1</I>和<I>2-2</I>在H1下是错误的。
问题是,当模板copyI找到和H时,我无法逃离它。由于源结构是平面的(都是同级结构),恐怕递归copyI没有帮助。
有什么建议吗?
非常感谢。尼古拉
如何扩展您的解决方案?
托玛拉克,非常感谢你的帮助。实际上,我的需求要复杂一些,而且您的解决方案是不可伸缩的。在我的源代码中,可以选择呈现一个<C>第三层,它以层次结构依赖于<I>。
<root>
<H>1</H>
<I>1-1</I>
<C>1-1-1</C>
<I>1-2</I>
<C>1-2-1</C>
<I>1-3</I>
<H>2</H>
<I>2-1</I>
<I>2-2</I>
<C>2-2-1</C>
</root>而预期的产出是
<root>
<H>1
<I>1-1<C>1-1-1</C></I>
<I>1-2<C>1-2-1</C></I>
<I>1-3</I>
</H>
<H>2
<I>2-1</I>
<I>2-2<C>2-2-1</C></I>
</H>
</root>再次感谢尼古拉
发布于 2014-10-22 15:20:13
这很简单:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes" />
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates select="H" />
</xsl:copy>
</xsl:template>
<xsl:template match="H">
<xsl:variable name="myId" select="generate-id()" />
<xsl:copy>
<xsl:copy-of select="text()[normalize-space() != '']" />
<xsl:copy-of select="
following-sibling::I[generate-id(preceding-sibling::H[1]) = $myId]
" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>对于每个<H>,您需要复制以下<I>元素,这些元素的直接前面的<H>与当前的<H>相同(通过比较generate-id()的结果,在generate-id()中建立节点标识)。
输出:
<root>
<H>1<I>1-1</I><I>1-2</I><I>1-3</I></H>
<H>2<I>2-1</I><I>2-2</I></H>
</root>缩进取决于您使用的XSLT处理程序,但是由于不重要的空格是.无足轻重,你不应该太担心这个。
如果您喜欢XSL键,您可以通过使用XSL键来实现相同的目标:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes" />
<xsl:key name="kI" match="I" use="generate-id(preceding-sibling::H[1])" />
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates select="H" />
</xsl:copy>
</xsl:template>
<xsl:template match="H">
<xsl:copy>
<xsl:copy-of select="text()[normalize-space() != '']" />
<xsl:copy-of select="key('kI', generate-id())" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>该键可以提高大输入文档的性能。
https://stackoverflow.com/questions/26510737
复制相似问题