关于递归:XSLT:来自父/子结构的递归字符串连接

XSLT : recursive string concatenation from parent/child structure

我需要一个我无法找到解决方案的主题的帮助(而且我很着急...)
我在XSLT方面的平均水平很高,这点超出了我的技能范围。

我的源XML有一个组织为Child / Parent的树结构,已经将顶部节点排在了前面。

EDITED:添加了顶部顶部的Department节点。
这是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<AllDepartments>
 <Department>
  <wyn>1</wyn>
  <ParentCode></ParentCode>
  <Label>IT</Label>
 </Department>
 <Department>
  <wyn>2</wyn>
  <ParentCode>1</ParentCode>
  <Label>Security</Label>
 </Department>
 <Department>
  <wyn>3</wyn>
  <ParentCode>2</ParentCode>
  <Label>SSO</Label>
 </Department>
</AllDepartments>

我希望将输出格式化为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<AllDepartments>
 <Department>
    <wyn>1</wyn>
    <ParentCode></ParentCode>
    <Label>IT</Label>
  </Department>
  <Department>
    <wyn>2</wyn>
    <ParentCode>1</ParentCode>
    <Label>Security</Label>
  </Department>
  <Department>
    <wyn>3</wyn>
    <ParentCode>1.2</ParentCode>
    <Label>SSO</Label>
  </Department>
</AllDepartments>

这意味着,一旦我达到第3级,ParentCode应该是所有ParentCode祖先(包括ParentCode本身)的串联,并以点作为分隔符。
级别的最大深度为7,因此我正在寻找一种递归级联算法。

我尝试了一些我感到很ham愧无法显示的XSL(尝试调用模板,应用模板)...
我一直在寻找类似的主题,发现了一些但不像我的情况那么"简单"的主题。

任何帮助将不胜感激(允许使用XSLT 2.0)。


首先,您将需要一个格式正确的XML输入,其中包含单个根元素,例如:

XML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<Departments>
   <Department>
      <wyn>1</wyn>
      <ParentCode/>
      <Label>IT</Label>
   </Department>
   <Department>
      <wyn>2</wyn>
      <ParentCode>1</ParentCode>
      <Label>Security</Label>
   </Department>
   <Department>
      <wyn>3</wyn>
      <ParentCode>2</ParentCode>
      <Label>SSO</Label>
   </Department>
</Departments>

然后您可以使用:

XSLT 1.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:key name="parent" match="Department" use="Code" />

<xsl:template match="ParentCode">
    <xsl:copy>
        <xsl:apply-templates select="key('parent', .)" mode="parent"/>
        <xsl:value-of select="."/>
    </xsl:copy>
</xsl:template>

<xsl:template match="Department" mode="parent">
    <xsl:if test="string(ParentCode)">
        <xsl:apply-templates select="key('parent', ParentCode)" mode="parent"/>
        <xsl:value-of select="ParentCode"/>
        <xsl:text>.</xsl:text>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

获得:

结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<Departments>
   <Department>
      <wyn>1</wyn>
      <ParentCode/>
      <Label>IT</Label>
   </Department>
   <Department>
      <wyn>2</wyn>
      <ParentCode>1</ParentCode>
      <Label>Security</Label>
   </Department>
   <Department>
      <wyn>3</wyn>
      <ParentCode>1.2</ParentCode>
      <Label>SSO</Label>
   </Department>
</Departments>