使用 for-each-group 将平面 XML 转换为嵌套
convert flat XML to nested using for-each-group
我不得不承认在理解如何使用 for-each-group 时惨败。我已经尝试过分组、相邻分组,但我得到了任意结果,这些结果违背了我对我做错了什么的理解。
我有以下输入 XML,它是 'flat':里面的所有元素都是兄弟,我需要转换它以创建一个嵌套结构。
<document>
<separator style="XXX"/>
<paragraph style="aaa">
<p>text1</p>
</paragraph>
<paragraph style="bbb">
<p>text2</p>
</paragraph>
<paragraph style="list1">
<p>text3</p>
</paragraph>
<paragraph style="list1">
<p>text4</p>
</paragraph>
<paragraph style="list1">
<p>text5</p>
</paragraph>
<paragraph style="ccc">
<p>text6</p>
</paragraph>
<separator style="YYY"/>
<paragraph style="ddd">
<p>text7</p>
</paragraph>
<paragraph style="ddd">
<p>text8</p>
</paragraph>
<paragraph style="ddd">
<p>text9</p>
</paragraph>
<paragraph style="list1">
<p>text10</p>
</paragraph>
<paragraph style="list1">
<p>text11</p>
</paragraph>
<paragraph style="ddd">
<p>text12</p>
</paragraph>
我需要以下输出:
<document>
<separator style="XXX">
<paragraph style="aaa">
<p>text1</p>
</paragraph>
<paragraph style="bbb">
<p>text2</p>
</paragraph>
<list>
<paragraph style="list1">
<p>text3</p>
</paragraph>
<paragraph style="list1">
<p>text4</p>
</paragraph>
<paragraph style="list1">
<p>text5</p>
</paragraph>
</list>
<paragraph style="ccc">
<p>text6</p>
</paragraph>
</separator>
<separator style="YYY">
<paragraph style="ddd">
<p>text7</p>
</paragraph>
<paragraph style="ddd">
<p>text8</p>
</paragraph>
<paragraph style="ddd">
<p>text9</p>
</paragraph>
<list>
<paragraph style="list1">
<p>text10</p>
</paragraph>
<paragraph style="list1">
<p>text11</p>
</paragraph>
</list>
</separator>
我没有包含我已经尝试过的任何 XSL,因为它显然不正确!
规则不是一个样例说出来的而是看XSLT sample是否有帮助(tail
是XPath/XSLT 3,实在卡住就用subsequence(current-group(), 2)
使用 XSLT 2):
<xsl:template match="document">
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="separator">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="tail(current-group())" group-adjacent="@style">
<xsl:choose>
<xsl:when test="starts-with(current-grouping-key(), 'list')">
<list>
<xsl:apply-templates select="current-group()"/>
</list>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
我不得不承认在理解如何使用 for-each-group 时惨败。我已经尝试过分组、相邻分组,但我得到了任意结果,这些结果违背了我对我做错了什么的理解。
我有以下输入 XML,它是 'flat':里面的所有元素都是兄弟,我需要转换它以创建一个嵌套结构。
<document>
<separator style="XXX"/>
<paragraph style="aaa">
<p>text1</p>
</paragraph>
<paragraph style="bbb">
<p>text2</p>
</paragraph>
<paragraph style="list1">
<p>text3</p>
</paragraph>
<paragraph style="list1">
<p>text4</p>
</paragraph>
<paragraph style="list1">
<p>text5</p>
</paragraph>
<paragraph style="ccc">
<p>text6</p>
</paragraph>
<separator style="YYY"/>
<paragraph style="ddd">
<p>text7</p>
</paragraph>
<paragraph style="ddd">
<p>text8</p>
</paragraph>
<paragraph style="ddd">
<p>text9</p>
</paragraph>
<paragraph style="list1">
<p>text10</p>
</paragraph>
<paragraph style="list1">
<p>text11</p>
</paragraph>
<paragraph style="ddd">
<p>text12</p>
</paragraph>
我需要以下输出:
<document>
<separator style="XXX">
<paragraph style="aaa">
<p>text1</p>
</paragraph>
<paragraph style="bbb">
<p>text2</p>
</paragraph>
<list>
<paragraph style="list1">
<p>text3</p>
</paragraph>
<paragraph style="list1">
<p>text4</p>
</paragraph>
<paragraph style="list1">
<p>text5</p>
</paragraph>
</list>
<paragraph style="ccc">
<p>text6</p>
</paragraph>
</separator>
<separator style="YYY">
<paragraph style="ddd">
<p>text7</p>
</paragraph>
<paragraph style="ddd">
<p>text8</p>
</paragraph>
<paragraph style="ddd">
<p>text9</p>
</paragraph>
<list>
<paragraph style="list1">
<p>text10</p>
</paragraph>
<paragraph style="list1">
<p>text11</p>
</paragraph>
</list>
</separator>
我没有包含我已经尝试过的任何 XSL,因为它显然不正确!
规则不是一个样例说出来的而是看XSLT sample是否有帮助(tail
是XPath/XSLT 3,实在卡住就用subsequence(current-group(), 2)
使用 XSLT 2):
<xsl:template match="document">
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="separator">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="tail(current-group())" group-adjacent="@style">
<xsl:choose>
<xsl:when test="starts-with(current-grouping-key(), 'list')">
<list>
<xsl:apply-templates select="current-group()"/>
</list>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>