2011-09-26 60 views
2

我一直在嘗試使用XSLT將一些簡單的XML轉換爲另一個簡單的XML。我是XSLT的新手,所以如果有人能給我一個例子,我會擴展它。xml xslt變換

我有任意的XML文件:e.g

<element> 
<child_element> 
    <grandchild_element> 
    only one 
    </grandchild_element> 
</child_element> 
<child_element> 
    <grandchild_element> 
    one 
    </grandchild_element> 
    <grandchild_element> 
    two 
    </grandchild_element> 
</child_element> 
</element> 

從中我希望產生:

<tree> 
<item class="element" id="1"> 
    <item class="child_element" id="11"> 
    <item class="grandchild_element" id="111" value="only one"/> 
    </item> 
    <item class="child_element" id="12"> 
    <item class="grandchild_element" id="121" value="only one"/> 
    <item class="grandchild_element" id="122" value="only one"/> 
    </item> 
</item> 
</tree> 

謝謝!

回答

0

最簡單的/最短的解決方案(僅3模板沒有模式的,沒有軸,沒有count(),只有一個xsl:attribute),它同時是最通用的(與任何元素名稱一起使用)

<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:template match="/"> 
    <tree> 
    <xsl:apply-templates/> 
    </tree> 
</xsl:template> 

<xsl:template match="*"> 
    <xsl:variable name="vNumber"> 
    <xsl:number count="*" level="multiple"/> 
    </xsl:variable> 

    <item class="{name()}" 
     id="{translate($vNumber, '.', '')}"> 
    <xsl:apply-templates/> 
    </item> 
</xsl:template> 

<xsl:template match="text()"> 
    <xsl:attribute name="value"> 
    <xsl:value-of select="normalize-space()"/> 
    </xsl:attribute> 
</xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔施加:

<element> 
<child_element> 
    <grandchild_element> 
    only one 
    </grandchild_element> 
</child_element> 
<child_element> 
    <grandchild_element> 
    one 
    </grandchild_element> 
    <grandchild_element> 
    two 
    </grandchild_element> 
</child_element> 
</element> 

有用,正確的結果產生

<tree> 
    <item class="element" id="1"> 
     <item class="child_element" id="11"> 
     <item class="grandchild_element" id="111" value="only one"/> 
     </item> 
     <item class="child_element" id="12"> 
     <item class="grandchild_element" id="121" value="one"/> 
     <item class="grandchild_element" id="122" value="two"/> 
     </item> 
    </item> 
</tree> 
0

你會寫出每個元素的模板,如:

<xsl:template match="child_element"> 

,使用前或前同輩元素的個數,以獲得「ID」字段:

<xsl:template match="child_element"> 
    <item> 
     <xsl:attribute name="id"> 
      <xsl:value-of select="concat(count(preceding-sibling::element),count(preceding::child_element)+1)"/> 
     </xsl:attribute> 
    </item> 
</xsl:template> 

對於孫女身份證,你必須玩...和前兄弟姐妹。 但是,我強烈建議您不要使用您當前的ID計數方案:一旦您在任何級別有超過10個節點,就會發生衝突。

0

要獲取每個元素的id,您需要回顧每個祖先,並且爲每個級別計算前面兄弟的數量。

<xsl:attribute name="id"> 
    <xsl:apply-templates select="ancestor-or-self::*" mode="id"/> 
</xsl:attribute> 

<xsl:template match="*" mode="id"> 
    <xsl:value-of select="count(preceding-sibling::*) + 1"/> 
</xsl:template> 

元素名稱轉換爲屬性是直接的,和做像這樣:

<xsl:attribute name="class"> 
    <xsl:value-of select="local-name()"/> 
</xsl:attribute> 

而且將文本轉換爲屬性也相當簡單。

<xsl:template match="text()"> 
    <xsl:attribute name="value"> 
     <xsl:value-of select="normalize-space(.)"/> 
    </xsl:attribute> 
</xsl:template> 

正常化空間這裏是去除示例XML顯示的換行符。

以下是完整的XSLT

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

    <!-- Match root element --> 
    <xsl:template match="/"> 
     <tree> 
     <xsl:apply-templates select="node()"/> 
     </tree> 
    </xsl:template> 

    <!-- Match any element in the XML --> 
    <xsl:template match="*"> 
     <item> 
     <xsl:attribute name="id"> 
      <xsl:apply-templates select="ancestor-or-self::*" mode="id"/> 
     </xsl:attribute> 
     <xsl:attribute name="class"> 
      <xsl:value-of select="local-name()"/> 
     </xsl:attribute> 
     <xsl:apply-templates select="@*|node()"/> 
     </item> 
    </xsl:template> 

    <!-- Used to match ancestors to work out the id --> 
    <xsl:template match="*" mode="id"> 
     <xsl:value-of select="count(preceding-sibling::*) + 1"/> 
    </xsl:template> 

    <!-- Convert text into the value attribute --> 
    <xsl:template match="text()"> 
     <xsl:attribute name="value"> 
     <xsl:value-of select="normalize-space(.)"/> 
     </xsl:attribute> 
    </xsl:template> 

    <!-- Copy any existing attributes in the XML --> 
    <xsl:template match="@*"> 
     <xsl:copy/> 
    </xsl:template> 
</xsl:stylesheet> 

當示例XML應用,下面是輸出:

<tree> 
    <item id="1" class="element"> 
     <item id="11" class="child_element"> 
     <item id="111" class="grandchild_element" value="only one"/> 
     </item> 
     <item id="12" class="child_element"> 
     <item id="121" class="grandchild_element" value="one"/> 
     <item id="122" class="grandchild_element" value="two"/> 
     </item> 
    </item> 
</tree>