2012-07-05 99 views
3

我有以下XML: -XSLT選擇不匹配的元素?

<inventory> 
    <item> 
    <name_element> 
     <!--some structure--> 
    </name_element> 
    <some_element1>val1</some_element1> 
    <some_element2>val2</some_element2> 
    <!-- some more elements --> 
    </item> 
    <!-- lots of items --> 
</inventory> 

現在我想將其轉換爲: -

<inventory> 
    <item some_element1="val1" some_element2="val2" ... > 
    <name_element> 
     <!-- as it is --> 
    </name_element> 
</inventory> 

基本上我不知道的名字/類型some_elements,並可以在任何項目任何東西有任何數量的這些元素。我知道他們都是簡單的類型,可以轉換爲屬性。

我讀過Converting XML elements to XML attributes using XSLT,它告訴我如何將所有子元素轉換爲屬性,但是我不清楚如何將特定的'name_element'轉換爲屬性。

回答

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

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

    <xsl:template match="item"> 
     <xsl:copy> 
      <!--apply templates for any attributes and convert 
       elements(except for name_element) in order to create all 
       attributes before creating child nodes for item element --> 
      <xsl:apply-templates select="@* 
             | *[not(self::name_element)]"/> 
      <!--apply templates to name_element and any comments or processing instructions --> 
      <xsl:apply-templates select="name_element 
             | comment() 
             | processing-instruction()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="item/*[not(self::name_element)]"> 
     <xsl:attribute name="{local-name()}"> 
      <xsl:value-of select="."/> 
     </xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 
+1

+1,用於適應''不存在但仍然可能的場景,其具有需要複製的先前屬性。 – ABach 2012-07-05 16:56:26

3

首先,使用身份模板複製每個事情是:

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

然後,定義的模板項目。您可以迭代子項,並排除不想轉換爲屬性的內容。這是一個示例模板:

<xsl:template match="item"> 
<xsl:copy> 
    <!-- this will set children as attributes, but name_element --> 
    <xsl:for-each select="*[not(local-name()='name_element')]"> 
     <xsl:attribute name="{local-name()}"> 
      <xsl:value-of select="text()"/> 
     </xsl:attribute> 
    </xsl:for-each> 

    <!-- this preserves name_element as it is --> 
    <xsl:apply-templates select="name_element"/> 
</xsl:copy> 
</xsl:template> 
+0

感謝@Mads,我剛剛意識到miscode。 – 2012-07-05 16:02:57

+0

謝謝。它看起來像應該工作!讓我測試一下。 – owagh 2012-07-05 16:09:25

1

嘗試

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

    <xsl:template match="item"> 
     <xsl:copy> 
      <xsl:apply-templates select="*[not(self::name_element)]"/> 
      <xsl:apply-templates select="name_element"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="item/*[not(self::name_element)]"> 
     <xsl:attribute name="{name()}"> 
      <xsl:value-of select="."/> 
     </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 
相關問題