Nesting flat XML siblings

心已入冬 提交于 2019-12-25 07:47:59

问题


Attemping to transform XML with XSLT 2.0.

Flat Source XML:

<body>
  <R1/>
  <R1/>
  <R2/>
  <R2/>
  <R2/>
  <R3/>
  <R3/>
  <R3/>
  <R1/>
  <R1/>
  <R2/>
  <R2/>
  <R1/>
</body>

Desired Output:

<body>
  <R1/>
  <R1>
    <R2/>
    <R2/>
    <R2>
       <R3/>
       <R3/>
       <R3/>
    </R2>
  </R1>
  <R1/>
  <R1>
    <R2/>
    <R2/>
  </R1>
  <R1/>
</body>

Basically these R1 - R3 elements signify sect-1, sect-2, sect-3 type elements. R2's are nested within their previous sibling R1 and R3's are nested within their previous sibling R2. Elements that are the same are on the same level.


回答1:


Use for-each-group group-starting-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"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs mf"
    version="2.0">

<xsl:param name="prefix" as="xs:string" select="'R'"/>

<xsl:output indent="yes"/>

<xsl:function name="mf:group" as="element()*">
  <xsl:param name="elements" as="element()*"/>
  <xsl:param name="level" as="xs:integer"/>
  <xsl:for-each-group select="$elements" group-starting-with="*[local-name() = concat($prefix, $level)]">
    <xsl:element name="{name()}">
      <xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
    </xsl:element>
  </xsl:for-each-group>
</xsl:function>

<xsl:template match="body">
  <xsl:copy>
    <xsl:sequence select="mf:group(*, 1)"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>


来源:https://stackoverflow.com/questions/27406846/nesting-flat-xml-siblings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!