如何使用XSLT组装XML层次结构

如何使用XSLT组装XML层次结构,xslt,Xslt,鉴于此XML 我想抓住每一个兄弟姐妹的集合,并将它们组合成自己的层次结构 每个具有parentId值的“Thing”节点都应该嵌套在相应的Thing节点下。 每个具有parentId值的“Foo”节点都应该嵌套在相应的Foo节点下,但只能嵌套在其同级节点内。该示例有两组Foo同级 我正在尝试创建以下内容: 这个例子很接近: 我使用标识模板来保留所有节点和属性。然后,我希望在具有同级(后面或前面)的所有节点上匹配覆盖模板,以便同级的@parentId值等于我的@id值。我能做的最接近的事

鉴于此XML


我想抓住每一个兄弟姐妹的集合,并将它们组合成自己的层次结构

每个具有parentId值的“Thing”节点都应该嵌套在相应的Thing节点下。 每个具有parentId值的“Foo”节点都应该嵌套在相应的Foo节点下,但只能嵌套在其同级节点内。该示例有两组Foo同级

我正在尝试创建以下内容:


这个例子很接近:

我使用标识模板来保留所有节点和属性。然后,我希望在具有同级(后面或前面)的所有节点上匹配覆盖模板,以便同级的@parentId值等于我的@id值。我能做的最接近的事情就是硬编码一个id/parentId值来匹配


我看不出如何获取当前节点@id值,以便在基于parentId值的Xpath匹配同级的谓词中使用


然后我想将当前节点的同级嵌套在它下面,同级@ParentId等于我的@id。

首先,请注意提供的XML文档中有一个错误:

    <Foo id="12" parentId="14"/>
    <Foo id="13" parentId="11"/>
    <Foo id="14" parentId="12"/>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kElemById" match="*"
   use="concat(generate-id(..), '+', @id)"/>
 <xsl:key match="*" name="kDescendants"
  use="concat(generate-id(key('kElemById', 
                              concat(generate-id(..), '+',@parentId))),
             '+', @parentId)"/>

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

 <xsl:template match="/*">
  <Xml>
   <xsl:apply-templates select="*[not(@parentId)]"/>
  </Xml>
 </xsl:template>

 <xsl:template match="*/*">
   <xsl:copy>
    <xsl:apply-templates select="@*"/>

    <xsl:apply-templates select="*[not(@parentId)]"/>

    <xsl:apply-templates select=
       "key('kDescendants', concat(generate-id(), '+',  @id))"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>
<Xml>
    <Thing id="1"  >
        <Foo id="11" parentId="12"/>
        <Foo id="12"/>
    </Thing>
    <Thing id="2" parentId="1" />
    <Thing id="3" parentId="2" />
    <Thing id="4">
        <Foo id="11" parentId="15"/>
        <Foo id="12" parentId="14"/>
        <Foo id="13" parentId="11"/>
        <Foo id="14" parentId="12"/>
        <Foo id="15"/>
    </Thing>
</Xml>
<Xml>
   <Thing id="1">
      <Foo id="12">
         <Foo id="11" parentId="12"/>
      </Foo>
      <Thing id="2" parentId="1">
         <Thing id="3" parentId="2"/>
      </Thing>
   </Thing>
   <Thing id="4">
      <Foo id="15">
         <Foo id="11" parentId="15">
            <Foo id="13" parentId="11"/>
         </Foo>
      </Foo>
   </Thing>
</Xml>
应用于提供的XML文档时

    <Foo id="12" parentId="14"/>
    <Foo id="13" parentId="11"/>
    <Foo id="14" parentId="12"/>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kElemById" match="*"
   use="concat(generate-id(..), '+', @id)"/>
 <xsl:key match="*" name="kDescendants"
  use="concat(generate-id(key('kElemById', 
                              concat(generate-id(..), '+',@parentId))),
             '+', @parentId)"/>

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

 <xsl:template match="/*">
  <Xml>
   <xsl:apply-templates select="*[not(@parentId)]"/>
  </Xml>
 </xsl:template>

 <xsl:template match="*/*">
   <xsl:copy>
    <xsl:apply-templates select="@*"/>

    <xsl:apply-templates select="*[not(@parentId)]"/>

    <xsl:apply-templates select=
       "key('kDescendants', concat(generate-id(), '+',  @id))"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>
<Xml>
    <Thing id="1"  >
        <Foo id="11" parentId="12"/>
        <Foo id="12"/>
    </Thing>
    <Thing id="2" parentId="1" />
    <Thing id="3" parentId="2" />
    <Thing id="4">
        <Foo id="11" parentId="15"/>
        <Foo id="12" parentId="14"/>
        <Foo id="13" parentId="11"/>
        <Foo id="14" parentId="12"/>
        <Foo id="15"/>
    </Thing>
</Xml>
<Xml>
   <Thing id="1">
      <Foo id="12">
         <Foo id="11" parentId="12"/>
      </Foo>
      <Thing id="2" parentId="1">
         <Thing id="3" parentId="2"/>
      </Thing>
   </Thing>
   <Thing id="4">
      <Foo id="15">
         <Foo id="11" parentId="15">
            <Foo id="13" parentId="11"/>
         </Foo>
      </Foo>
   </Thing>
</Xml>

生成正确的结果,排除任何无法访问的元素

    <Foo id="12" parentId="14"/>
    <Foo id="13" parentId="11"/>
    <Foo id="14" parentId="12"/>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kElemById" match="*"
   use="concat(generate-id(..), '+', @id)"/>
 <xsl:key match="*" name="kDescendants"
  use="concat(generate-id(key('kElemById', 
                              concat(generate-id(..), '+',@parentId))),
             '+', @parentId)"/>

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

 <xsl:template match="/*">
  <Xml>
   <xsl:apply-templates select="*[not(@parentId)]"/>
  </Xml>
 </xsl:template>

 <xsl:template match="*/*">
   <xsl:copy>
    <xsl:apply-templates select="@*"/>

    <xsl:apply-templates select="*[not(@parentId)]"/>

    <xsl:apply-templates select=
       "key('kDescendants', concat(generate-id(), '+',  @id))"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>
<Xml>
    <Thing id="1"  >
        <Foo id="11" parentId="12"/>
        <Foo id="12"/>
    </Thing>
    <Thing id="2" parentId="1" />
    <Thing id="3" parentId="2" />
    <Thing id="4">
        <Foo id="11" parentId="15"/>
        <Foo id="12" parentId="14"/>
        <Foo id="13" parentId="11"/>
        <Foo id="14" parentId="12"/>
        <Foo id="15"/>
    </Thing>
</Xml>
<Xml>
   <Thing id="1">
      <Foo id="12">
         <Foo id="11" parentId="12"/>
      </Foo>
      <Thing id="2" parentId="1">
         <Thing id="3" parentId="2"/>
      </Thing>
   </Thing>
   <Thing id="4">
      <Foo id="15">
         <Foo id="11" parentId="15">
            <Foo id="13" parentId="11"/>
         </Foo>
      </Foo>
   </Thing>
</Xml>


提供的XML文档中有一个细微的错误——一对无法访问的
Foo
元素,它们构成一个闭合回路,不能成为层次结构的一部分。请说对。不管这个I+1这个问题,因为它很有趣。错误更正。谢谢对不起,太棒了!非常感谢你,迪米特。这是非常有用的。