2012-12-02 38 views
3

我想要轉換XML,使得特定名稱的所有節點都包含這些節點下可用的所有元素的超集。在XML中識別節點下的標記的超集

例如,這裏是輸入xml。在這個XML中,該組可以包含一個或多個項目節點。來電者只會通過該組下可用的項目。

<group> 
    <item> 
     <name> item1 </name> 
     <value> 10 </value> 
    </item> 
</group> 
<group> 
    <item> 
     <name> item2 </name> 
     <value> 20 </value> 
    </item> 
</group> 

要求是將其變換到如下所示的一個,其中,從所有組的項目節點應各組的一部分。但是,如果該項目不在該組下的輸入可用,應該與0

<group> 
    <item> 
     <name> item1 </name> 
     <value> 10 </value> 
    </item> 
    <item> 
     <name> item2 </name> 
     <value> 0 </value> 
    </item> 
</group> 
<group> 
    <item> 
     <name> item1 </name> 
     <value> 0 </value> 
    </item>  
    <item> 
     <name> item2 </name> 
     <value> 20 </value> 
    </item> 
</group> 

值填充可否請你讓我知道如何可以使用XSLT來實現?

由於

+0

只需添加,的下的內容不是一個當中每定義的設置,並且可以具有任何用戶給定值。 –

+0

歡迎來到Stack Overflow。 +1爲一個好的第一個問題(雖然你已經嘗試過的例子會很好)。 –

回答

0

這兩者XSLT 1.0和XSLT 2.0溶液

<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:variable name="vGroupContent" select="/*/group/node()"/> 

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

<xsl:template match="group"> 
    <group> 
    <xsl:apply-templates select= 
    "node()|@*|$vGroupContent[not(name = current()/item/name)]"> 
    <xsl:with-param name="pGroup" select="."/> 
    <xsl:sort select="name"/> 
    </xsl:apply-templates> 
    </group> 
</xsl:template> 

<xsl:template match="item"> 
    <xsl:param name="pGroup"/> 
    <item> 
    <xsl:apply-templates select="name"/> 
    <value> <xsl:value-of select= 
    "value/text()[generate-id($pGroup) = generate-id(../../..)]"/> 

    <xsl:if test= 
    "value/text()[not(generate-id($pGroup) = generate-id(../../..))]"> 0 </xsl:if> 
    </value> 
    </item> 
</xsl:template> 
</xsl:stylesheet> 

當在下面的XML文檔被應用於這種轉變:

<t> 
    <group> 
     <item> 
      <name> item1 </name> 
      <value> 10 </value> 
     </item> 
    </group> 
    <group> 
     <item> 
      <name> item2 </name> 
      <value> 20 </value> 
     </item> 
    </group> 
</t> 

的想要得到正確的結果:

<t> 
    <group> 
     <item> 
     <name> item1 </name> 
     <value> 10 </value> 
     </item> 
     <item> 
     <name> item2 </name> 
     <value> 0 </value> 
     </item> 
    </group> 
    <group> 
     <item> 
     <name> item1 </name> 
     <value> 0 </value> 
     </item> 
     <item> 
     <name> item2 </name> 
     <value> 20 </value> 
     </item> 
    </group> 
</t> 
+0

我相信你錯過了「'但是,如果該項目在該組下的輸入中不可用,它應該填充0的值。」'問題的一部分。 –

+0

@DevNull,現在更正。 –

+0

感謝您的快速解決方案。 –

1

以下是我會做它(在XSLT 2.0,因爲你沒有指定)...

XML輸入(包裹在<groups>被很好地形成)

<groups> 
    <group> 
     <item> 
      <name> item1 </name> 
      <value> 10 </value> 
     </item> 
    </group> 
    <group> 
     <item> 
      <name> item2 </name> 
      <value> 20 </value> 
     </item> 
    </group> 
</groups> 

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="names" select="distinct-values(/*/group/item/name)"/> 

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

    <xsl:template match="group"> 
     <xsl:variable name="currentItems" select="item/name"/> 
     <xsl:variable name="items" as="node()*"> 
      <xsl:apply-templates select="item"/> 
      <xsl:for-each select="$names[not(. = current()/item/name)]"> 
       <item> 
        <name><xsl:value-of select="."/></name> 
        <value> 0 </value> 
       </item> 
      </xsl:for-each>   
     </xsl:variable> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
      <xsl:perform-sort select="$items"> 
       <xsl:sort select="name"/> 
      </xsl:perform-sort> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

XML輸出

<groups> 
    <group> 
     <item> 
     <name> item1 </name> 
     <value> 10 </value> 
     </item> 
     <item> 
     <name> item2 </name> 
     <value> 0 </value> 
     </item> 
    </group> 
    <group> 
     <item> 
     <name> item1 </name> 
     <value> 0 </value> 
     </item> 
     <item> 
     <name> item2 </name> 
     <value> 20 </value> 
     </item> 
    </group> 
</groups>