2011-01-12 47 views
1

我需要使用xslt转换XML。基于子元素值和序列号对父节点进行分组

逻辑:

拆分如果具有不同子地址和父母的名字追加序列号父父。还需要孩子的线路号码。 这里我们可能有多个父节点,每个父节点可能有更多的子节点。

我已经尝试了很多方法来实现这一点,我坚持在foreach中生成序列号。所以任何人都可以尝试并为此提供解决方案。

源如下XML:

<Data> 
    <Parent> 
     <Name>P1</Name> 
     <Child> 
     <Name>CName1</Name> 
     <Address>Address1</Address> 
     </Child> 
     <Child> 
     <Name>CName2</Name> 
     <Address>Address2</Address> 
     </Child> 
     <Child> 
     <Name>CName3</Name> 
     <Address>Address1</Address> 
     </Child> 
    </Parent> 

    <Parent> 
    <Name>P2</Name> 
     <Child> 
     <Name>CName1</Name> 
     <Address>Address1</Address> 
     </Child> 
    </Parent> 
</Data> 

目标XML应如下:

<Data> 
    <Parent> 
    <Name>P1_1</Name> 
    <Address>Address1</Address> 
    <Child> 
     <LineNumber>1</LineNumber> 
     <Name>CName1</Name> 
    </Child> 
    <Child> 
     <LineNumber>2</LineNumber> 
     <Name>CName3</Name> 
    </Child> 
    </Parent> 

    <Parent> 
     <Name>P1_2</Name> 
     <Address>Address2</Address> 
     <Child> 
     <LineNumber>1</LineNumber> 
     <Name>CName2</Name> 
     </Child> 
    </Parent> 

    <Parent> 
     <Name>P2_1</Name> 
     <Address>Address1</Address> 
     <Child> 
      <LineNumber>1</LineNumber> 
      <Name>CName1</Name> 
     </Child> 
    </Parent> 
</Data> 
+0

请使用{}按钮格式化代码 – bluish 2011-01-12 15:52:46

+0

对于分组问题,您确实需要告诉我们您是否可以使用XSLT 2.0,或者您是否使用XSLT 1.0。使用2.0时,分组更容易*。另外,如果你已经解决了问题的一部分(分组),并且与其他部分(编号)卡在一起,那么告诉我们你有多远 - 这可能需要一个相当小的调整,或者你的方法可能已经完全误导。 – 2011-01-12 16:12:44

回答

3

这XSLT 1.0转化:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:key name="kAddress" match="Child" use="concat(generate-id(..), '|', Address)" /> 

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

    <xsl:template match="Parent"> 
    <xsl:variable name="parent" select="." /> 
    <xsl:for-each select="Child[ 
     generate-id() 
     = 
     generate-id(key('kAddress', concat(generate-id($parent), '|', Address))[1]) 
    ]"> 
     <Parent> 
     <Name><xsl:value-of select="concat(../Name, '_', position())" /></Name> 
     <xsl:copy-of select="Address" /> 
     <xsl:apply-templates select=" 
      key('kAddress', concat(generate-id($parent), '|', Address)) 
     " /> 
     </Parent> 
    </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="Child"> 
    <xsl:copy> 
     <xsl:copy-of select="@*" /> 
     <LineNumber><xsl:value-of select="position()" /></LineNumber> 
     <xsl:apply-templates select="node()[not(self::Address)]" /> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

生成用于您的样品下面的输出:

<Data> 
    <Parent> 
     <Name>P1_1</Name> 
     <Address>Address1</Address> 
     <Child> 
      <LineNumber>1</LineNumber> 
      <Name>CName1</Name> 
     </Child> 
     <Child> 
      <LineNumber>2</LineNumber> 
      <Name>CName3</Name> 
     </Child> 
    </Parent> 
    <Parent> 
     <Name>P1_2</Name> 
     <Address>Address2</Address> 
     <Child> 
      <LineNumber>1</LineNumber> 
      <Name>CName2</Name> 
     </Child> 
    </Parent> 
    <Parent> 
     <Name>P2_1</Name> 
     <Address>Address1</Address> 
     <Child> 
      <LineNumber>1</LineNumber> 
      <Name>CName1</Name> 
     </Child> 
    </Parent> 
</Data> 
相关问题