【问题标题】:group and merge xml nodes based on specific child nodes根据特定子节点对 xml 节点进行分组和合并
【发布时间】:2017-10-23 21:51:54
【问题描述】:

我是 xslt 的新手,遇到了一个非常棘手的组合并案例。我有以下 xml 结构:

<root>
  <section name="A"> 
    <table name="B">
      <row1/>
    </table>
  </section>
  <section name="A"> 
    <table name="B">
      <row1/>
    </table>
  </section>
  <section name="A"> 
    <table name="B">
      <row1/>
    </table>
    <section name="C"></section>
  </section>
  <section name="A"> 
    <table name="B">
      <row1/>
    </table>
  </section>
  <section name="A"> 
    <table name="B">
      <row1/>
    </table>
  </section>
</root>

我需要以某种方式对其进行转换,以使代码只合并 row1 直到它遇到一个包含名称为 c 的子节的节:

<root>
   <section name="A"> 
     <table name="B">
       <row1/>
       <row1/>
     </table>
   </section>
   <section name="A"> 
     <table name="B">
      <row1/>
     </table>
     <section name="C"></section>
   </section>
    <section name="A"> 
     <table name="B">
       <row1/>
       <row1/>
     </table>
   </section>
</root>

到目前为止,我只是合并了所有部分中的所有行:

<xsl:template match="section[@name='A' and following-sibling::section[@name='A'] ]//table[1]" >
   <xsl:copy>
        <xsl:apply-templates select="@*" />
                        <xsl:apply-templates select="ancestor::section[@name='A']/following-sibling::section[@name='A']//table[1]/row1" />
    </xsl:copy>
</xsl:template>
<xsl:template match="section[ @name='A' and preceding-sibling::section[@name='A'] ]//table[1]" />

请帮帮我。

【问题讨论】:

    标签: xml xslt-2.0


    【解决方案1】:

    嗯,使用 XSLT 2.0,您应该熟悉 (https://www.w3.org/TR/xslt20/#grouping-examples) 和 for-each-group 及其各种选项,如 group-bygroup-adjacentgroup-starting/ending-with,然后您可以想出

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="xs"
        version="2.0">
    
        <xsl:output indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="@* | node()" mode="#all">
            <xsl:copy>
                <xsl:apply-templates select="@* , node()" mode="#current"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="root">
            <xsl:copy>
                <xsl:for-each-group select="*" group-adjacent="boolean(self::section[@name = 'A' and not(section[@name = 'C'])])">
                    <xsl:choose>
                        <xsl:when test="current-grouping-key()">
                            <xsl:apply-templates select="." mode="merge"/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:apply-templates select="current-group()"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each-group>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="row1" mode="merge">
            <xsl:copy-of select="current-group()//row1"/>
        </xsl:template>
    
    </xsl:stylesheet>
    

    哪个输出

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
       <section name="A">
          <table name="B">
             <row1/>
             <row1/>
          </table>
       </section>
       <section name="A">
          <table name="B">
             <row1/>
          </table>
          <section name="C"/>
       </section>
       <section name="A">
          <table name="B">
             <row1/>
             <row1/>
          </table>
       </section>
    </root>
    

    【讨论】:

    • 感谢这就像一个宝石,但是我有一个关于 for-each 循环的小问题:循环是否保留了它处理节点的顺序,或者它是 current-group() 函数这是哪个?
    • 你问的是for-each-group吗?它按人口顺序处理select="*选择的分组人口,并形成一个接一个的组。详情请见w3.org/TR/xslt20/#xsl-for-each-group
    猜你喜欢
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 2017-03-29
    • 2015-01-18
    • 2015-05-15
    • 2020-08-26
    • 1970-01-01
    相关资源
    最近更新 更多