2012-02-24 110 views
1

我想用XSLT進行轉換。這是我的XML數據源:罕見的XSLT轉換

<Memoria> 
    <seccion> 
    <contenido><p>TEXT</p> 
    <ul> 
     <li>LIST</li> 
    </ul> 
    <p>ANOTHER TEXT</p> 
    <p>&amp;nbsp;</p></contenido> 
    </seccion>  
</Memoria> 

我試圖使用XSLT這樣的:

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

<xsl:output method="xml" indent="yes"/> 
<xsl:template match="/Memoria"> 
<cosa> 
    <xsl:for-each select="seccion"> 
    <Address> 
    <xsl:for-each select="contenido"> 
    <FirstName><xsl:value-of select="p" /></FirstName> 
    </xsl:for-each> 
    <ul> 
     <LastName><xsl:value-of select="ul/li" /></LastName> 
    </ul> 
    </Address> 
    </xsl:for-each> 
</cosa> 
</xsl:template> 

</xsl:stylesheet> 

而得到這樣的:

<?xml version="1.0"?> 
<cosa> 
    <Address> 
    <FirstName>TEXT</FirstName> 
    <ul> 
     <LastName>LIST</LastName> 
    </ul> 
    </Address> 
</cosa> 

但我相信:

<?xml version="1.0"?> 
<cosa> 
    <Address> 
    <FirstName>TEXT</FirstName> 
    <ul> 
     <LastName>LISTr</LastName> 
    </ul> 
    <FirstName>ANOTHER TEXT</FirstName> 
    </Address> 
</cosa> 

我從外部應用程序獲取這個XML。

+2

我不知道什麼是 「罕見」 這個問題。 – 2012-02-24 22:03:50

+0

可能是因爲他很少使用XSL轉換..;) – 2012-02-25 08:36:15

回答

0

xsl:value-of將獲取節點集中第一個元素的內容。如果您想操作集合中的所有元素,則需要xsl:for-eachxsl:apply-templates。但是,如果你這樣做,你會得到:

<?xml version="1.0"?> 
<cosa> 
    <Address> 
    <FirstName>TEXT</FirstName> 
    <ul> 
     <LastName>LISTr</LastName> 
    </ul> 
    <FirstName>ANOTHER TEXT</FirstName> 
    <FirstName>&amp;&nbsp;</FirstName> 
    </Address> 
</cosa> 
0

假設你肯定知道,你永遠有名字的第一個P元素,和第二名字在第二個P元素,你可以使用一個共同的節點集()函數來獲取裏面的特定元素的for-each循環:

以下修改XSLT生成所需的輸出,你已經把你的問題:

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:exsl="http://exslt.org/common"> 

    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/Memoria"> 
    <cosa> 
     <xsl:for-each select="seccion"> 
     <Address> 
      <xsl:for-each select="contenido"> 
      <FirstName> 
       <xsl:value-of select="p" /> 
      </FirstName> 
      <ul> 
       <LastName> 
       <xsl:value-of select="ul/li" /> 
       </LastName> 
      </ul> 
      <FirstName> 
       <xsl:value-of select="exsl:node-set(.)/p[2]/."/> 
      </FirstName> 
      </xsl:for-each> 
     </Address> 
     </xsl:for-each> 
    </cosa> 
    </xsl:template> 

</xsl:stylesheet> 

注:我通常使用的xmlns :msxsl =「urn:schemas-microsoft-com:xslt」用於node-set()函數,但我認爲exsl不是供應商特定的:)

如果您的XML結構不一致或可預測,這很可能會中斷;否則它將起作用,並且不需要另一個for-each來獲取第二個FirstName結果元素的第二個P元素。

我希望這有幫助!

+0

我會嘗試這個,因爲我的代碼是可變的如果ul標籤不存在,我可以做同樣的事情嗎?謝謝 – user1075738 2012-02-25 10:50:58

+0

如果存在,可以使用xsl:if test語法添加條件來拉取ul標籤。 – 2012-02-25 14:16:41

1

我不知道究竟要達到什麼......但是,下面的XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/Memoria"> 
     <cosa> 
      <xsl:for-each select="seccion"> 
       <Address> 
        <xsl:apply-templates select="contenido" /> 
       </Address> 
      </xsl:for-each> 
     </cosa> 
    </xsl:template> 

    <xsl:template match="contenido"> 
     <xsl:apply-templates select="p | ul" /> 
    </xsl:template> 

    <xsl:template match="p"> 
     <FirstName> 
      <xsl:value-of select="text()"/> 
     </FirstName> 
    </xsl:template> 

    <xsl:template match="ul"> 
     <ul> 
      <LastName> 
       <xsl:value-of select="li"/> 
      </LastName> 
     </ul> 
    </xsl:template> 

</xsl:stylesheet> 

將產生以下的輸出:

<?xml version="1.0" encoding="UTF-8"?> 
<cosa> 
    <Address> 
     <FirstName>TEXT</FirstName> 
     <ul> 
      <LastName>LIST</LastName> 
     </ul> 
     <FirstName>ANOTHER TEXT</FirstName> 
     <FirstName>&amp;nbsp;</FirstName> 
    </Address> 
</cosa> 

現在你可能認爲加入的條件,以排除&amp;&nbsp;元件從輸出:

<xsl:template match="p"> 
    <xsl:if test="not(contains(text(), '&amp;'))"> 
    <FirstName> 
     <xsl:value-of select="text()"/> 
    </FirstName> 
    </xsl:if> 
</xsl:template> 
3

難得的轉型?提供了一個合適的輸入XML和期望的輸出,它不會在XSLT中罕見..
老實說,我不滿意您的示例輸入和輸出XML。我想出了一個XML希望這就是你的XML的樣子。如果不是,則調出精確的I/P和O/P XML。

<?xml version="1.0" encoding="utf-8"?> 
<Memoria> 
    <seccion> 
    <contenido> 
     <p>TEXT</p> 
     <ul> 
     <li>Item1</li> 
     <li>Item2</li> 
     <li>Item3</li> 
     </ul> 
     <p>ANOTHER TEXT</p> 
     <ul> 
     <li>Itema</li> 
     <li>Itemb</li> 
     <li>Itemc</li> 
     </ul> 
    </contenido> 
    </seccion> 
</Memoria> 

通訊XSLT代碼:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
    <cosa> 
     <xsl:apply-templates select="//contenido"/> 
    </cosa> 
    </xsl:template> 

    <xsl:template match="text()"/> 

    <xsl:template match="contenido"> 
    <Address> 
     <xsl:apply-templates select="p|ul"/> 
    </Address> 
    </xsl:template> 

    <xsl:template match="p[not(contains(.,'&amp;'))]"> 
    <FirstName> 
     <xsl:value-of select="."/> 
    </FirstName> 
    </xsl:template> 

    <xsl:template match="ul"> 
    <ul> 
     <xsl:for-each select="li"> 
    <LastName> 
     <xsl:value-of select="."/> 
    </LastName> 
     </xsl:for-each> 
    </ul> 
    </xsl:template> 

</xsl:stylesheet> 
+0

謝謝,我錯誤地使用了模板,但是你的代碼很好地解釋了它是如何工作的。 – user1075738 2012-02-25 10:49:05

+0

@ user1075738,除了我粗魯的話之前:)很高興知道我可以幫忙(Y) – 2012-02-25 18:25:10