2016-06-09 500 views
0

我很難編寫XSLT將具有相同屬性值的所有節點移動到同一級別。使用XSLT拼合嵌套的XML

下面是一個例子:

<root> 
    <object Name="1"> 
     <Property Name="a1" Value="a"> 
      <Property Name="a1.1" Value="a"/> 
      <Property Name="a1.2" Value="a"> 
       <Property Name="a1.2.1" Value="a"/> 
       <Property Name="a1.2.2" Value="a"/> 
      </Property> 
     </Property> 
     <Property Name="b1" Value="b"/> 
    </object> 
</root> 

目前,它是可以嵌套屬性具有值在彼此內部(沒有用於節點的量或嵌套級別沒有限制)。此模型將更改爲只允許在對象級別使用此類屬性。 應該是這樣的改造(元素的順序並不重要),其後:

<root> 
    <object Name="1"> 
     <Property Name="a1" Value="a"/> 
     <Property Name="a1.1" Value="a"/> 
     <Property Name="a1.2" Value="a"> 
     <Property Name="a1.2.1" Value="a"/> 
     <Property Name="a1.2.2" Value="a"/> 
     <Property Name="b1" Value="b"/> 
    </object> 
</root> 

我試着this very similar question解決這個,主要的區別在於,本例中的節點將不被複制,但其值將被使用。我一直無法弄清楚如何複製整個節點。

編輯
上面的例子已經過於簡化了。屬性將包含子元素,這將有被複制,以及改造後

<root> 
    <object Name="1"> 
     <Property Name="a1" Value="a"> 
      <x>x1</x> 
      <y>y1</y> 
      <z>z1</z> 
      <Property Name="a1.1" Value="a"> 
       <x>x1.1</x> 
       <y>y1.1</y> 
       <z>z1.1</z> 
      </Property> 
      <Property Name="a1.2" Value="a"> 
       <x>x1.2</x> 
       <y>y1.2</y> 
       <z>z1.2</z> 
       <Property Name="a1.2.1" Value="a"> 
        <x>x1.2.1</x> 
        <y>y1.2.1</y> 
        <z>z1.2.1</z> 
       </Property> 
       <Property Name="a1.2.2" Value="a"> 
        <x>x1.2.1</x> 
        <y>y1.2.1</y> 
        <z>z1.2.1</z> 
       </Property> 
      </Property> 
     </Property> 
     <Property Name="b1" Value="b"/> 
    </object> 
</root> 

應該成爲這樣的:

<root> 
    <object Name="1"> 
     <Property Name="a1" Value="a"> 
      <x>x1</x> 
      <y>y1</y> 
      <z>z1</z> 
     </Property> 
     <Property Name="a1.1" Value="a"> 
      <x>x1.1</x> 
      <y>y1.1</y> 
      <z>z1.1</z> 
     </Property> 
     <Property Name="a1.2" Value="a"> 
      <x>x1.2</x> 
      <y>y1.2</y> 
      <z>z1.2</z> 
     </Property> 
     <Property Name="a1.2.1" Value="a"> 
      <x>x1.2.1</x> 
      <y>y1.2.1</y> 
      <z>z1.2.1</z> 
     </Property> 
     <Property Name="a1.2.2" Value="a"> 
      <x>x1.2.1</x> 
      <y>y1.2.1</y> 
      <z>z1.2.1</z> 
     </Property> 
     <Property Name="b1" Value="b"/> 
    </object> 
</root> 

回答

1

重新編輯過的問題 - 試試這樣說:

XSLT 1.0

<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:template match="Property"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()[not(self::Property)]"/> 
    </xsl:copy> 
    <xsl:apply-templates select="Property" /> 
</xsl:template> 

</xsl:stylesheet> 
2

如果你開始用XSLT identity template,所有你需要的是另一種匹配Property的模板,該模板複製元素和屬性,但將元素之後的子元素輸出,而不是輸出元素和屬性。

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

試試這個XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" /> 
    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

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

請注意,我假設Property元素只能包含其他元素Property這裏的孩子。

+0

感謝您的幫助。我已經簡化了這個例子(我編輯了我的問題)。要複製的節點還包含其他子節點,而不是必須複製的屬性。使用XSLT,屬性節點會丟失其內容。 – Philippe