xslt - 将子元素拆分为子部分

标签 xslt

给定以下 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>

谓词找到那些跟随兄弟 item 的人当前元素title谁最近的前title是我们的起点。

这两种方法之间的一个区别是,如果您在 section 中有任何其他元素|在第一个之前title , 然后是 for-each-group方法会将它们放在前导小节中(没有标题),而 1.0 方法将忽略它们。


如果你总是想要恰好两个小节(第二小节中第二个title之后的所有内容,包括任何进一步的title元素)那么你可以将它硬编码为

<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/> 元素)

关于xslt - 将子元素拆分为子部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28589114/

相关文章:

xml - XSLT 应用模板选择中的 "@*|node()"是什么意思?

php - 在 Localhost XML 正在生成,但在服务器中它正在创建 Empty Xml

c# - 将重复组转换为多个文本行

XSLT 按字母顺序和数字顺序排序问题

XSLT 1.0 以及如何在文本中找到一些关键字

xslt - 使用 XSLT 变量保存属性的问题

xml - 需要一个 XPath 来检查任何子、孙或曾孙等的属性值

xslt - XPath 1.0 : Finding count of nodes before a specified node

java - 将文档根节点与前缀匹配

xslt - 删除 XSLT 中引号内的空格