2017-02-11 111 views
1

我有一個XML文件是這樣的:將XML元素XSLT

<?xml version="1.0" encoding="UTF-8"?> 
    <i xmlns="http://stuff.com" > 
     <v> 
      <iNumber>0118</iNumber> 
      <s>1</s> 
      <a>24</a> 
      <p>2175</p> 
      <p>2175</p> 
      <p>4534</p> 
     </v> 
    </i> 

但我需要出口到這個樣子。

<?xml version="1.0" encoding="UTF-8"?> 
    <i xmlns="http://stuff.com" > 
     <v> 
      <iNumber>0118</iNumber> 
      <s>1</s> 
      <a>24</a> 
      <p>2175</p> 
     </v> 
     <v> 
      <iNumber>0118</iNumber> 
      <s>1</s> 
      <a>24</a> 
      <p>2175</p> 
     </v> 
      <iNumber>0118</iNumber> 
      <s>1</s> 
      <a>24</a> 
      <p>4534</p> 
     </v> 
    </i> 

我是新來的XSLT,所以我想一些幫助,改造這個XML請

這裏是我的嘗試:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
       xmlns:stuff="http://stuff.com" exclude-result-prefixes="stuff"> 
<xsl:output version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" /> 
<xsl:strip-space elements="*"/> 

<xsl:template match="stuff:v"> 
    <xsl:copy> 
     <xsl:copy-of select="ancestor::stuff:v/stuff:p"/> 
    <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

我已經更新了我的問題,以顯示我嘗試

+2

你有一個具體的問題或困難?或者你只是想找人幫你做點工作? –

+0

我想寫一些幫助 – 1122335

+1

開始寫作,我們會幫助你,當你卡住了。 –

回答

1

這應該是訣竅:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:stuff="http://stuff.com" exclude-result-prefixes="stuff"> 

    <xsl:output version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" /> 

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

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

    <xsl:template match="stuff:v"> 
     <xsl:for-each select="stuff:p"> 
      <xsl:apply-templates select="ancestor::stuff:v" mode="copying"> 
       <xsl:with-param name="pId" select="generate-id()" /> 
      </xsl:apply-templates> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="stuff:v" mode="copying"> 
     <xsl:param name="pId" /> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"> 
       <xsl:with-param name="pId" select="$pId" /> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="stuff:p"> 
     <xsl:param name="pId"/> 
     <xsl:if test="generate-id() = $pId"> 
      <xsl:copy-of select="." /> 
     </xsl:if> 
    </xsl:template> 

</xsl:stylesheet> 

一些解釋。匹配node()|@*的第一個模板只是默認複製東西。

匹配stuff:v的第二個模板將在遇到stuff:v元素時接管。它將遍歷所有東西:p元素,併爲它們中的每一個應用匹配模板的東西:v祖先。但是,它進入一個名爲「複製」的模式,並使用參數pId(它是p元素的ID)調用模板。 XML中的每個元素都有一些隱含的唯一標識它的標識。

這樣我們最終在下一個模板,它也匹配stuff:v但只在模式「複製」。它接受pId參數,複製v元素,然後將模板應用於其所有屬性和子節點,不再使用「複製」模式,但使用pId參數。最後一部分是至關重要的。

最終模板匹配stuff:p,但只會在該元素的id與pId參數中給定的元素相同時複製該模板。因此,基本上,我們得到的東西:v,通過每個東西:p在它中,每個人都會去東西:v再次以不同的模式來匹配另一個模板(否則它會無限遞歸),並從那裏複製一切,但對於東西:p元素要求它們匹配傳入模板的參數。

+1

非常感謝anser @G_H,它工作的很好,但唯一的是它不會複製'stuff:iNumber'。它複製一切,'stuff:s','stuff:a','stuff:p' – 1122335

+0

@ 1122335這很奇怪,它在我的測試中複製了iNumber元素。您用於測試的XML中是否有多個名稱空間?這是哪種XSLT處理器? –

+1

沒關係!我明白了,非常感謝你的答案! – 1122335

1

你爲什麼不這樣做簡單:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:stuff="http://stuff.com" 
exclude-result-prefixes="stuff"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/stuff:i"> 
    <i xmlns="http://stuff.com"> 
     <xsl:for-each select="stuff:v/stuff:p"> 
      <v> 
       <xsl:copy-of select="../*[not(self::stuff:p)]"/> 
       <xsl:copy-of select="."/> 
      </v> 
     </xsl:for-each> 
    </i> 
</xsl:template> 

</xsl:stylesheet>