xsl:for-each-group 位置分组平面 xml 到分层 [英] xsl:for-each-group positional grouping flat xml to hierarchical
问题描述
我有一个平面 xml 文件需要转换为层次结构.我使用了这里 xsl:for-each-group help needed 中的嵌套分组想法.除了几个问题外,它在大多数情况下都有效:
I have a flat xml file that needs to be converted to hierarchical. I used the nested grouping idea from here xsl:for-each-group help needed. It's working for the most part except for a couple of issues:
1) 元素 root1 和 root2 没有出现.
1) The elements root1 and root2 are not showing up.
2) NFActy 元素的位置不正确.第一个 NFActy 应该在 2 个 Rot 元素之间.
2) The location of element NFActy is incorrect. The first NFActy should be between the 2 Rot elements.
3) 责任与义务NFActy 元素被视为一组用于计算 SequenceCount.
3) The Duty & NFActy elements are treated as one group for calculating the SequenceCount.
4) 对于 Leg 元素,一个职责内的每组 Leg 元素都应分组,以便为 leg 元素进行 SequenceCount.
4) For Leg elements each set of Leg elements within one duty should be grouped for SequenceCount for leg elements.
非常感谢任何帮助.
谢谢.
输入 XML
<root>
<root1>1234</root1>
<root2>5678</root2>
<Schedule>
<a>line 1</a>
<b>line 2</b>
<c>line 3</c>
</Schedule>
<Rot>
<d>line 4</d>
<e>line 5</e>
<f>line 6</f>
<g>line 7</g>
</Rot>
<Duty>
<h>line 8</h>
<i>line 9</i>
<j>line 10</j>
<k>line 11</k>
<l>line 12</l>
</Duty>
<Leg>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
</Leg>
<Leg>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
</Leg>
<NFActy>
<d>line 214</d>
<e>line 215</e>
<f>line 216</f>
<g>line 217</g>
</NFActy>
<Rot>
<d>line 19</d>
<e>line 20</e>
<f>line 21</f>
<g>line 22</g>
</Rot>
<Duty>
<h>line 23</h>
<i>line 24</i>
<j>line 25</j>
<k>line 26</k>
<l>line 27</l>
</Duty>
<Leg>
<m>line 28</m>
<n>line 29</n>
<o>line 30</o>
</Leg>
<Leg>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
</Leg>
<NFActy>
<d>line 224</d>
<e>line 225</e>
<f>line 226</f>
<g>line 227</g>
</NFActy>
所需的输出 XML
<root>
<root1>1234</root1>
<root2>5678</root2>
<Schedule>
<a>line 1</a>
<b>line 2</b>
<c>line 3</c>
<Rot>
<d>line 4</d>
<e>line 5</e>
<f>line 6</f>
<g>line 7</g>
<Duty>
<SequenceCount>1</SequenceCount>
<h>line 8</h>
<i>line 9</i>
<j>line 10</j>
<k>line 11</k>
<l>line 12</l>
<Leg>
<SequenceCount>1</SequenceCount>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
</Leg>
<Leg>
<SequenceCount>2</SequenceCount>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
</Leg>
</Duty>
</Rot>
<NFActy>
<SequenceCount>2</SequenceCount>
<d>line 214</d>
<e>line 215</e>
<f>line 216</f>
<g>line 217</g>
</NFActy>
<Rot>
<d>line 19</d>
<e>line 20</e>
<f>line 21</f>
<g>line 22</g>
<Duty>
<SequenceCount>3</SequenceCount>
<h>line 23</h>
<i>line 24</i>
<j>line 25</j>
<k>line 26</k>
<l>line 27</l>
<Leg>
<SequenceCount>1</SequenceCount>
<m>line 28</m>
<n>line 29</n>
<o>line 30</o>
</Leg>
<Leg>
<SequenceCount>2</SequenceCount>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
/Leg>
</Duty>
</Rot>
<NFActy>
<SequenceCount>4</SequenceCount>
<d>line 224</d>
<e>line 225</e>
<f>line 226</f>
<g>line 227</g>
</NFActy>
</Schedule>
我的 XSL
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="fn" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0"
exclude-result-prefixes="xs fn">
<xsl:output indent="yes" />
<xsl:template match="/">
<xsl:for-each-group select="*" group-starting-with="root">
<root>
<xsl:for-each-group select="*" group-starting-with="*[name(.)='Schedule']">
<xsl:choose>
<xsl:when test="name(.)='Schedule'">
<Schedule>
<xsl:apply-templates />
<xsl:for-each-group select="current-group()" group-starting-with="*[name(.)='Rot']">
<xsl:choose>
<xsl:when test="name(.)='Rot'">
<Rot>
<xsl:apply-templates />
<xsl:for-each-group select="current-group()" group-starting-with="*[name(.)='Duty']">
<xsl:choose>
<xsl:when test="name(.)='Duty'">
<Duty>
<xsl:element name="SequenceCount"><xsl:number count="Duty|NFActy" level="any"/></xsl:element>
<xsl:apply-templates />
<xsl:for-each-group select="current-group()" group-starting-with="*[name(.)='Leg']">
<xsl:choose>
<xsl:when test="name(.)='Leg'">
<Leg>
<xsl:element name="SequenceCount"><xsl:number value="position() - 1"/></xsl:element>
<xsl:apply-templates />
</Leg>
</xsl:when>
</xsl:choose>
</xsl:for-each-group>
</Duty>
</xsl:when>
</xsl:choose>
</xsl:for-each-group>
</Rot>
</xsl:when>
</xsl:choose>
</xsl:for-each-group>
<xsl:for-each-group select="current-group()" group-starting-with="*[name(.)='NFActy']">
<xsl:choose>
<xsl:when test="name(.)='NFActy'">
<NFActy>
<xsl:element name="SequenceCount"><xsl:number count="Duty|NFActy" level="any"/></xsl:element>
<xsl:apply-templates />
</NFActy>
</xsl:when>
</xsl:choose>
</xsl:for-each-group>
</Schedule>
</xsl:when>
</xsl:choose>
</xsl:for-each-group>
</root>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
推荐答案
这是我对您代码的编辑,您需要确保同时处理所有元素,而不是像顺序 for-每组
.
Here is my edit of your code, you need to make sure you process all elements at the same time and not as you had with sequential for-each-group
.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0"
exclude-result-prefixes="xs">
<xsl:output indent="yes" />
<xsl:template match="root">
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="Schedule">
<xsl:choose>
<xsl:when test="self::Schedule">
<Schedule>
<xsl:apply-templates />
<xsl:for-each-group select="current-group() except ." group-starting-with="Rot | NFActy">
<xsl:choose>
<xsl:when test="self::Rot | self::NFActy">
<xsl:copy>
<xsl:if test="self::NFActy">
<SequenceCount><xsl:number count="Duty | NFActy" level="any"/></SequenceCount>
</xsl:if>
<xsl:apply-templates />
<xsl:for-each-group select="current-group() except ." group-starting-with="Duty">
<xsl:choose>
<xsl:when test="self::Duty">
<xsl:copy>
<SequenceCount><xsl:number count="Duty | NFActy" level="any"/></SequenceCount>
<xsl:apply-templates />
<xsl:for-each-group select="current-group() except ." group-starting-with="Leg">
<xsl:choose>
<xsl:when test="self::Leg">
<Leg>
<SequenceCount><xsl:number value="position()"/></SequenceCount>
<xsl:apply-templates />
</Leg>
</xsl:when>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:for-each-group>
</Schedule>
</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="node()">
<xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当我将上述带有 Saxon 9.5 的样式表应用于输入时
When I apply above stylesheet with Saxon 9.5 to the input
<root>
<root1>1234</root1>
<root2>5678</root2>
<Schedule>
<a>line 1</a>
<b>line 2</b>
<c>line 3</c>
</Schedule>
<Rot>
<d>line 4</d>
<e>line 5</e>
<f>line 6</f>
<g>line 7</g>
</Rot>
<Duty>
<h>line 8</h>
<i>line 9</i>
<j>line 10</j>
<k>line 11</k>
<l>line 12</l>
</Duty>
<Leg>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
</Leg>
<Leg>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
</Leg>
<NFActy>
<d>line 214</d>
<e>line 215</e>
<f>line 216</f>
<g>line 217</g>
</NFActy>
<Rot>
<d>line 19</d>
<e>line 20</e>
<f>line 21</f>
<g>line 22</g>
</Rot>
<Duty>
<h>line 23</h>
<i>line 24</i>
<j>line 25</j>
<k>line 26</k>
<l>line 27</l>
</Duty>
<Leg>
<m>line 28</m>
<n>line 29</n>
<o>line 30</o>
</Leg>
<Leg>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
</Leg>
<NFActy>
<d>line 224</d>
<e>line 225</e>
<f>line 226</f>
<g>line 227</g>
</NFActy>
</root>
我得到了结果
<root>
<root1>1234</root1>
<root2>5678</root2>
<Schedule>
<a>line 1</a>
<b>line 2</b>
<c>line 3</c>
<Rot>
<d>line 4</d>
<e>line 5</e>
<f>line 6</f>
<g>line 7</g>
<Duty>
<SequenceCount>1</SequenceCount>
<h>line 8</h>
<i>line 9</i>
<j>line 10</j>
<k>line 11</k>
<l>line 12</l>
<Leg>
<SequenceCount>1</SequenceCount>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
</Leg>
<Leg>
<SequenceCount>2</SequenceCount>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
</Leg>
</Duty>
</Rot>
<NFActy>
<SequenceCount>2</SequenceCount>
<d>line 214</d>
<e>line 215</e>
<f>line 216</f>
<g>line 217</g>
</NFActy>
<Rot>
<d>line 19</d>
<e>line 20</e>
<f>line 21</f>
<g>line 22</g>
<Duty>
<SequenceCount>3</SequenceCount>
<h>line 23</h>
<i>line 24</i>
<j>line 25</j>
<k>line 26</k>
<l>line 27</l>
<Leg>
<SequenceCount>1</SequenceCount>
<m>line 28</m>
<n>line 29</n>
<o>line 30</o>
</Leg>
<Leg>
<SequenceCount>2</SequenceCount>
<m>line 13</m>
<n>line 14</n>
<o>line 15</o>
</Leg>
</Duty>
</Rot>
<NFActy>
<SequenceCount>4</SequenceCount>
<d>line 224</d>
<e>line 225</e>
<f>line 226</f>
<g>line 227</g>
</NFActy>
</Schedule>
</root>
这篇关于xsl:for-each-group 位置分组平面 xml 到分层的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!