我需要转换像这样的平面结构
<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>
H1下的<I>2-1</I>
和<I>2-2</I>
错误。
问题在于,当找到并且H时,我无法从模板copyI中逃脱 由于源结构扁平(所有兄弟姐妹),我害怕a 递归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>
再次感谢 尼古拉
答案 0 :(得分:0)
这很简单:
<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>
,您需要复制{em>直接位于 <I>
之前的<H>
个元素与当前元素相同的元素(在XSLT中建立节点标识)通过比较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: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>
密钥可以提高大型输入文档的性能。