XSLT 分组的限制?
Limits of XSLT Grouping?
我需要通过将相关元素分组到新组元素下,将下面的代码段更改为层次结构。 XSLT 听起来像是适合在这里使用的技术,但我对它的了解还不够多,无法评估它是否能够满足我的需要。示例分组标准是“1 'd' 节点后跟一定数量的‘3’节点,再后跟 1'f' 节点”。我必须针对几个单独的条件执行此任务,所以我想知道在 XSLT 中是否可以进行这种性质的查询,或者我是否会更好地放弃并按程序处理 DOM。我也完全接受其他策略。具体的例子,我需要转换这个-
<root>
<a>foo</a>
<b>bar</b>
<c>baz</c>
<d>location</d>
<e>3.14</e>
<e>6.02</e>
<e>1.23</e>
<f>2015</f>
<d>location</d>
<e>3.14</e>
<e>6.02</e>
<f>2015</f>
</root>
进入这个-
<root>
<a>foo</a>
<b>bar</b>
<c>baz</c>
<sample>
<d>location</d>
<e>3.14</e>
<e>6.02</e>
<e>1.23</e>
<f>2015</f>
</sample>
<sample>
<d>location</d>
<e>3.14</e>
<e>6.02</e>
<f>2015</f>
</sample>
</root>
考虑到我通常在 XSLT 1.0 环境中工作,这是我的一种方法。
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml"/>
<!-- any nodes that I don't address specifically, I copy -->
<xsl:template match="*">
<xsl:copy-of select="."/>
</xsl:template>
<!-- from the root, deal with a, b, c, d nodes -->
<xsl:template match="root">
<root>
<xsl:apply-templates select="a|b|c|d"/>
</root>
</xsl:template>
<!-- the d node is the fun one -->
<xsl:template match="d">
<!-- add the wrapper -->
<sample>
<!-- first, copy the d node -->
<xsl:copy-of select="."/>
<!--
process any following sibling e nodes if that
e node's immediately preceding d sibling is the
"current" node - i.e. the d node that got us here
We use the fact that in XSLT 1.0, a union of nodes
will never contain duplicates, so if the count is
one, that means the two parts of the union are the
same node
-->
<xsl:apply-templates select="following-sibling::e
[count(current() | preceding-sibling::d[1]) = 1]"/>
<!-- same logic for f nodes -->
<xsl:apply-templates select="following-sibling::f
[count(current() | preceding-sibling::d[1]) = 1]"/>
</sample>
</xsl:template>
</xsl:stylesheet>
现在,我想这是否会让您相信 XSLT 是正确的工具,或者让您惊恐地尖叫,取决于您的个性。
如果是要对元素进行分组,从d
开始,可以使用下面的方法。
XSLT-1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" />
<xsl:strip-space elements="*"/>
<!-- key to select following (e|f) elements using the first preceding d's id -->
<xsl:key name="following" match="e | f" use="generate-id(preceding::d[1])"/>
<!-- identity transform template -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- template to group d and its following (e|f) elements under sample element-->
<xsl:template match="d">
<sample>
<xsl:copy-of select="current() | key('following', generate-id())"/>
</sample>
</xsl:template>
<!-- template to do nothing for e|f elements -->
<xsl:template match="e|f"/>
</xsl:stylesheet>
当然,XSLT 不限于这种简单的分组。
我需要通过将相关元素分组到新组元素下,将下面的代码段更改为层次结构。 XSLT 听起来像是适合在这里使用的技术,但我对它的了解还不够多,无法评估它是否能够满足我的需要。示例分组标准是“1 'd' 节点后跟一定数量的‘3’节点,再后跟 1'f' 节点”。我必须针对几个单独的条件执行此任务,所以我想知道在 XSLT 中是否可以进行这种性质的查询,或者我是否会更好地放弃并按程序处理 DOM。我也完全接受其他策略。具体的例子,我需要转换这个-
<root>
<a>foo</a>
<b>bar</b>
<c>baz</c>
<d>location</d>
<e>3.14</e>
<e>6.02</e>
<e>1.23</e>
<f>2015</f>
<d>location</d>
<e>3.14</e>
<e>6.02</e>
<f>2015</f>
</root>
进入这个-
<root>
<a>foo</a>
<b>bar</b>
<c>baz</c>
<sample>
<d>location</d>
<e>3.14</e>
<e>6.02</e>
<e>1.23</e>
<f>2015</f>
</sample>
<sample>
<d>location</d>
<e>3.14</e>
<e>6.02</e>
<f>2015</f>
</sample>
</root>
考虑到我通常在 XSLT 1.0 环境中工作,这是我的一种方法。
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml"/>
<!-- any nodes that I don't address specifically, I copy -->
<xsl:template match="*">
<xsl:copy-of select="."/>
</xsl:template>
<!-- from the root, deal with a, b, c, d nodes -->
<xsl:template match="root">
<root>
<xsl:apply-templates select="a|b|c|d"/>
</root>
</xsl:template>
<!-- the d node is the fun one -->
<xsl:template match="d">
<!-- add the wrapper -->
<sample>
<!-- first, copy the d node -->
<xsl:copy-of select="."/>
<!--
process any following sibling e nodes if that
e node's immediately preceding d sibling is the
"current" node - i.e. the d node that got us here
We use the fact that in XSLT 1.0, a union of nodes
will never contain duplicates, so if the count is
one, that means the two parts of the union are the
same node
-->
<xsl:apply-templates select="following-sibling::e
[count(current() | preceding-sibling::d[1]) = 1]"/>
<!-- same logic for f nodes -->
<xsl:apply-templates select="following-sibling::f
[count(current() | preceding-sibling::d[1]) = 1]"/>
</sample>
</xsl:template>
</xsl:stylesheet>
现在,我想这是否会让您相信 XSLT 是正确的工具,或者让您惊恐地尖叫,取决于您的个性。
如果是要对元素进行分组,从d
开始,可以使用下面的方法。
XSLT-1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" />
<xsl:strip-space elements="*"/>
<!-- key to select following (e|f) elements using the first preceding d's id -->
<xsl:key name="following" match="e | f" use="generate-id(preceding::d[1])"/>
<!-- identity transform template -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- template to group d and its following (e|f) elements under sample element-->
<xsl:template match="d">
<sample>
<xsl:copy-of select="current() | key('following', generate-id())"/>
</sample>
</xsl:template>
<!-- template to do nothing for e|f elements -->
<xsl:template match="e|f"/>
</xsl:stylesheet>
当然,XSLT 不限于这种简单的分组。