XSL从非规范化数据集创建父子层次结构

时间:2013-02-14 19:55:02

标签: xml xslt

需要你的指导。

我正在尝试使用非规范化的XML创建父子XML:

FROM:

<Parent>Parent1</Parent>
<Child>Child1</Child>
<Parent>Parent2</Parent>
<Child>Child1</Child>
<Child>Child2</Child>
<Parent>Parent3</Parent>
<Child>Child1</Child>

TO:

<Parent>
<ParentValue>Parent1</ParentValue>
<Child>
    <ChildValue>Child1</ChildValue>
</Child>
</Parent>
<Parent>
<ParentValue>Parent2</ParentValue>
<Child>
    <ChildValue>Child1</ChildValue>
</Child>
<Child>
    <ChildValue>Child2</ChildValue>
</Child>
</Parent>
<Parent>
<ParentValue>Parent3</ParentValue>
<Child>
    <ChildValue>Child1</ChildValue>
</Child>
</Parent>

问题是我无法弄清楚要说的逻辑,在每个父元素之间获取所有Child元素。

感谢任何帮助。

非常感谢您对此进行调查。

1 个答案:

答案 0 :(得分:4)

在XSLT1.0中,您可以使用密钥来实现此目的。您实际上是按照第一个 Parent 元素对 Child 元素进行分组,因此您可以定义以下键:

<xsl:key name="child" match="Child" use="generate-id(preceding-sibling::Parent[1])"/>

然后,在与 Parent 元素匹配的模板中,您可以获得所有关联的 Child 元素,如下所示:

<xsl:apply-templates select="key('child', generate-id())"/>

在这种情况下,这是完整的XSLT。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:key name="child" match="Child" use="generate-id(preceding-sibling::Parent[1])"/>

   <xsl:template match="Family">
      <Family>
         <xsl:apply-templates select="Parent"/>
      </Family>
   </xsl:template>

   <xsl:template match="Parent">
      <Parent>
         <ParentValue>
            <xsl:value-of select="."/>
         </ParentValue>
         <xsl:apply-templates select="key('child', generate-id())"/>
      </Parent>
   </xsl:template>

   <xsl:template match="Child">
      <Child>
         <ChildValue>
            <xsl:value-of select="."/>
         </ChildValue>
      </Child>
   </xsl:template>
</xsl:stylesheet>

当应用于XML时,输出以下内容:

<Family>
   <Parent>
      <ParentValue>Parent1</ParentValue>
      <Child>
         <ChildValue>Child1</ChildValue>
      </Child>
   </Parent>
   <Parent>
      <ParentValue>Parent2</ParentValue>
      <Child>
         <ChildValue>Child1</ChildValue>
      </Child>
      <Child>
         <ChildValue>Child2</ChildValue>
      </Child>
   </Parent>
   <Parent>
      <ParentValue>Parent3</ParentValue>
      <Child>
         <ChildValue>Child1</ChildValue>
      </Child>
   </Parent>
</Family>

在XSLT2.0中,您可以使用 xsl:for-each-group 。在您的情况下,您希望将元素从元素开始分组。

<xsl:for-each-group select="*" group-starting-with="Parent">

然后选择儿童元素,您可以使用当前组功能:

<xsl:apply-templates select="current-group()[position() &gt; 1]" />

这是完整的XSLT for 2.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/Family">
     <Family>
      <xsl:for-each-group select="*" group-starting-with="Parent">
         <Parent>
            <ParentValue>
               <xsl:value-of select="."/>
            </ParentValue>
            <xsl:apply-templates select="current-group()[position() &gt; 1]" />
         </Parent>
      </xsl:for-each-group>
     </Family>
   </xsl:template>

   <xsl:template match="Child">
      <Child>
         <ChildValue>
            <xsl:value-of select="."/>
         </ChildValue>
      </Child>
   </xsl:template>
</xsl:stylesheet>

这也应该输出相同的结果: