2012-02-28 76 views
2

我在PHP開工項目,使用XML,現在我需要申請改造,使我發現首次XSL ...XSL添加屬性家長基於孩子

我所面臨的問題:如何建立XSL做如下改造: - 以「attrib-」開始轉變爲屬性的父節點的節點

例子:

<a1> 
    <b1> 
    <attrib-c1>12</attrib-c1> 
    <c2>23</c2> 
    </b1> 
</a1> 

應該變成:

<a1> 
    <b1 c1="12"> 
    <c2>23</c2> 
    </b1> 
</a1> 

我已經開始解決方案是這樣的:

<xsl:stylesheet> 
    <xsl:output method="xml"/> 
    <xsl:template match="@*|*|text()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|*|text()"/> 
    </xsl:copy> 
    </xsl:template> 
... 
</xsl:stylesheet> 

我需要一些幫助來解決這個任務。由於事先...

+0

所以你所做的只是複製一個身份轉換。你是否試圖解決這個問題?這是功課嗎? – 2012-02-28 20:47:02

回答

1

這幾乎是相同的溶液作爲DevNull的,但在萬一有一個現有的屬性,並通過一個子元素定義了新的一者之間的衝突,後者取代了以前

<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="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="*"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*"/> 
    <xsl:apply-templates mode="attr" select="*[starts-with(name(), 'attrib-')]"/> 
    <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template mode="attr" match="*[starts-with(name(), 'attrib-')]"> 
    <xsl:attribute name="{substring-after(name(), 'attrib-')}"> 
    <xsl:value-of select="."/> 
    </xsl:attribute> 
</xsl:template> 

<xsl:template match="*[starts-with(name(), 'attrib-')]"/> 
</xsl:stylesheet> 

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

<a1> 
    <b1 existing="attr" x="Y"> 
    <attrib-new>12</attrib-new> 
    <c2>23</c2> 
    <attrib-new2>ABCD</attrib-new2> 
    <attrib-x>Z</attrib-x> 
    </b1> 
</a1> 

想要的,正確的結果產生

<a1> 
    <b1 existing="attr" x="Z" new="12" new2="ABCD"> 
     <c2>23</c2> 
    </b1> 
</a1> 
+0

+1善於處理潛在的衝突。 – 2012-02-28 21:38:31

+0

偉大的解決方案。謝謝! – 2012-02-28 22:11:46

+0

@ZoranKalinić:不客氣。 – 2012-02-28 22:48:55

3

XML輸入(改性,以略微增加的複雜度。)

<a1> 
    <b1 existing="attr"> 
    <attrib-c1>12</attrib-c1> 
    <c2>23</c2> 
    <attrib-dh>DevNull</attrib-dh> 
    </b1> 
</a1> 

XSLT 1.0

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

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

    <xsl:template match="*"> 
    <xsl:copy> 
     <xsl:apply-templates select="*[starts-with(name(),'attrib')]" mode="attr"/> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*[starts-with(name(),'attrib')]"/> 

    <xsl:template match="*" mode="attr"> 
    <xsl:attribute name="{substring-after(name(),'-')}"> 
     <xsl:value-of select="."/> 
    </xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 

XML輸出

<a1> 
    <b1 c1="12" dh="DevNull" existing="attr"> 
     <c2>23</c2> 
    </b1> 
</a1> 
+0

+1很好的答案。另外,''可以替換爲'',對吧?你也可以將''改爲'」,因爲只有以'attrib-'開頭的元素纔會在該模式下處理。 – LarsH 2012-02-28 21:26:08

+0

@LarsH - 謝謝,這些都是很棒的建議。不知道爲什麼我沒有使用'xsl:copy';這就是我得到的衝動。 – 2012-02-28 21:35:13

+2

+1一個很好的答案。似乎拉爾斯忘記了實際上的贊成。 – 2012-02-28 21:42:37

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

    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <!-- match elements with children like attrib- and copy/pass --> 
    <xsl:template match="*[*[starts-with(name(.),'attrib')]]"> 
     <xsl:copy> 
     <xsl:apply-templates select="*[starts-with(name(.),'attrib')]"/> 
     <xsl:apply-templates select="@*|*[not(starts-with(name(.),'attrib'))]"/> 
     </xsl:copy> 
    </xsl:template> 

    <!-- match elements like attrib- and output them as attribute --> 
    <xsl:template match="*[starts-with(name(.),'attrib')]"> 
     <xsl:attribute name="{substring-after(name(.),'attrib-')}"> 
      <xsl:value-of select="."/> 
     </xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 
+1

很高興見到你回到了stackoverflow! +1對於一個好的答案 – 2012-02-28 21:39:20

+0

好,但要小心''' 。這不能複製元素以外的子元素(例如文本節點,註釋等)。 – LarsH 2012-02-28 21:52:20

+0

感謝您的回答! – 2012-02-28 22:12:26