我对xslt:
有这个问题这是输入文件:
<root>
<header/>
<item/>
… other n-1 <item/>
<header/>
<item/>
… other m-1 <item/>
</root>
所以标题和项目处于同一级别(/ root)。 它必须转换为:
<root2>
<header2>
<item2/>
…<item2/> // the first n-items up
</header2>
<header2>
<item2/>
…<item2/> // the last m-items up
</header2>
</root2>
所以基本上第一个n项必须在第一个标题中移动,而第二个项必须在第二个标题中移动。知道如何获得这个吗?
由于
随机化
答案 0 :(得分:1)
示例XML:
<root>
<header/>
<item>1</item>
<item>2</item>
<item>3</item>
<header/>
<item>5</item>
<item>6</item>
<item>7</item>
</root>
使用分组的XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="k" match="item" use="count(preceding-sibling::header)"/>
<xsl:template match="/">
<root2>
<xsl:apply-templates select="root/item[generate-id(.) = generate-id(key('k', count(preceding-sibling::header)))]" mode="a"/>
</root2>
</xsl:template>
<xsl:template match="item" mode="a">
<header2>
<xsl:apply-templates select="key('k', count(preceding-sibling::header))"/>
</header2>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
或简单的特定XSLT:
<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="/">
<root2>
<header2>
<xsl:apply-templates select="root/item[count(preceding-sibling::header) = 1]"/>
</header2>
<header2>
<xsl:apply-templates select="root/item[count(preceding-sibling::header) = 2]"/>
</header2>
</root2>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
两者产生相同的输出:
<root2>
<header2>
<item>1</item>
<item>2</item>
<item>3</item>
</header2>
<header2>
<item>5</item>
<item>6</item>
<item>7</item>
</header2>
</root2>
答案 1 :(得分:0)
这是一个更简单,更有效的XSLT 1.0解决方案,而不是计算所有前面的兄弟:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kFollowing" match="item"
use="generate-id(preceding-sibling::header[1])"/>
<xsl:template match="/*">
<root>
<xsl:apply-templates select="header"/>
</root>
</xsl:template>
<xsl:template match="header">
<heather2>
<xsl:copy-of select="key('kFollowing', generate-id())"/>
</heather2>
</xsl:template>
</xsl:stylesheet>
将此转换应用于以下XML文档:
<root>
<header/>
<item>1</item>
<item>2</item>
<item>3</item>
<header/>
<item>5</item>
<item>6</item>
<item>7</item>
</root>
产生了想要的正确结果:
<root>
<heather2>
<item>1</item>
<item>2</item>
<item>3</item>
</heather2>
<heather2>
<item>5</item>
<item>6</item>
<item>7</item>
</heather2>
</root>
<强>解释:
按键的定义方式是,对于header
,任何紧随其后的item
元素都与此generate-id()
的{{1}}匹配。
<强> II。 XSLT 2.0解决方案:
header
将此转换应用于同一XML文档(上图)时,会生成相同的正确结果:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<root>
<xsl:for-each-group select="item"
group-adjacent=
"generate-id(preceding-sibling::header[1])">
<header2>
<xsl:sequence select="current-group()"/>
</header2>
</xsl:for-each-group>
</root>
</xsl:template>
</xsl:stylesheet>
解释:使用<root>
<header2>
<item>1</item>
<item>2</item>
<item>3</item>
</header2>
<header2>
<item>5</item>
<item>6</item>
<item>7</item>
</header2>
</root>
,xsl:for-each-group
,group-adjacent