将 child 个元素拆分为子部分
split child elements into sub sections
给出以下 XML
<section>
<title>Title1</title>
<item>Item1</item>
<item>Item2</item>
<title>Title2</title>
<item>Item1</item>
<item>Item2</item>
</section>
将第二个标题拆分成这个的最简单方法是什么
<section>
<subsection>
<title>Title1</title>
<item>Item1</item>
<item>Item2</item>
</subsection>
<subsection>
<title>Title2</title>
<item>Item1</item>
<item>Item2</item>
</subsection>
</section>
例如,以下模板是一种想法,但 xpath 似乎很棘手。
<xsl:template match="section">
<xsl:copy>
<subsection>
<xsl:apply-templates select="...those before second title..."/>
</subsection>
<subsection>
<xsl:apply-templates select="...those including and after second title..."/>
</subsection>
</xsl:copy>
</xsl:template>
对于 XSLT 2.0 或更高版本,可以直接使用 for-each-group
:
<xsl:template match="section">
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="title">
<subsection>
<xsl:apply-templates select="current-group()"/>
</subsection>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
在1.0中你可以用这种逻辑实现类似的效果:
<xsl:template match="section">
<xsl:copy>
<xsl:for-each select="title">
<subsection>
<xsl:apply-templates select=". | following-sibling::item[
generate-id(preceding-sibling::title[1])
= generate-id(current())]"/>
</subsection>
</xsl:for-each>
</xsl:copy>
</xsl:template>
谓词查找当前 title
的同级 item
元素之后的元素,其最接近的前面 title
是我们开始的元素。
这两种方法之间的一个区别是,如果您在 第一个 title
之前的 section
中有任何其他元素,那么 for-each-group
] 方法会将它们放在前导小节中(没有标题),而 1.0 方法将忽略它们。
如果您总是想要 正好两个 小节(第二小节中第二个 title
之后的所有内容,包括任何进一步的 title
元素),那么您可以hard-code它作为
<xsl:template match="section">
<xsl:copy>
<subsection>
<xsl:apply-templates select="title[2]/preceding-sibling::*"/>
</subsection>
<subsection>
<xsl:apply-templates select="title[2] | title[2]/following-sibling::*"/>
</subsection>
</xsl:copy>
</xsl:template>
(请注意,如果少于两个 title
元素,这将导致两个完全空的 <subsection/>
元素)
给出以下 XML
<section>
<title>Title1</title>
<item>Item1</item>
<item>Item2</item>
<title>Title2</title>
<item>Item1</item>
<item>Item2</item>
</section>
将第二个标题拆分成这个的最简单方法是什么
<section>
<subsection>
<title>Title1</title>
<item>Item1</item>
<item>Item2</item>
</subsection>
<subsection>
<title>Title2</title>
<item>Item1</item>
<item>Item2</item>
</subsection>
</section>
例如,以下模板是一种想法,但 xpath 似乎很棘手。
<xsl:template match="section">
<xsl:copy>
<subsection>
<xsl:apply-templates select="...those before second title..."/>
</subsection>
<subsection>
<xsl:apply-templates select="...those including and after second title..."/>
</subsection>
</xsl:copy>
</xsl:template>
对于 XSLT 2.0 或更高版本,可以直接使用 for-each-group
:
<xsl:template match="section">
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="title">
<subsection>
<xsl:apply-templates select="current-group()"/>
</subsection>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
在1.0中你可以用这种逻辑实现类似的效果:
<xsl:template match="section">
<xsl:copy>
<xsl:for-each select="title">
<subsection>
<xsl:apply-templates select=". | following-sibling::item[
generate-id(preceding-sibling::title[1])
= generate-id(current())]"/>
</subsection>
</xsl:for-each>
</xsl:copy>
</xsl:template>
谓词查找当前 title
的同级 item
元素之后的元素,其最接近的前面 title
是我们开始的元素。
这两种方法之间的一个区别是,如果您在 第一个 title
之前的 section
中有任何其他元素,那么 for-each-group
] 方法会将它们放在前导小节中(没有标题),而 1.0 方法将忽略它们。
如果您总是想要 正好两个 小节(第二小节中第二个 title
之后的所有内容,包括任何进一步的 title
元素),那么您可以hard-code它作为
<xsl:template match="section">
<xsl:copy>
<subsection>
<xsl:apply-templates select="title[2]/preceding-sibling::*"/>
</subsection>
<subsection>
<xsl:apply-templates select="title[2] | title[2]/following-sibling::*"/>
</subsection>
</xsl:copy>
</xsl:template>
(请注意,如果少于两个 title
元素,这将导致两个完全空的 <subsection/>
元素)