2012-06-27 163 views
2

我有以下XML:XML合併節點

<Root>  
     <Item> 
      <CityCode>ALV</CityCode> 
      <AirportCode>ALV</AirportCode> 
      <CityName>ANDORRA LA VELLA</CityName> 
      <AirportName>Andorra La Vella Hlpt</AirportName> 
      <StateCode></StateCode> 
      <CountryCode>AD</CountryCode> 
      <AirportTypeCode>8</AirportTypeCode> 
      <AirportTypeName>Heliport, not scheduled</AirportTypeName>  
     </Item>  
</Root> 

,我需要一個XSLT得到這個:

<Root> 
    <Item> 
    <CityCode>ALV</CityCode> 
    <CityName>ANDORRA LA VELLA</CityName> 
    <CityNameComplete> ANDORRA LA VELLA (ALV) - Andorra La Vella Hlpt </CityNameComplete> 
    <Item> 
<Root> 

我知道如何獲得第2個節點,我不知道如何「插入」最後一個。

回答

0

以下是可處理缺失的<AirportCode>和/或的版本:

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

    <!--Identity template. Matches everything that isn't matched 
     by another template and copies it without modification.--> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Item"> 
     <!--Copy the current element (Item) to the output.--> 
     <xsl:copy> 
      <!--Apply templates to attributes of Item and also the 
      CityCode and CityName elements. All other nodes of 
      Item will not be processed.--> 
      <xsl:apply-templates select="CityCode|CityName|@*"/> 
      <CityNameComplete> 
       <!--Output the value of CityName.--> 
       <xsl:value-of select="CityName"/> 
       <!--Apply the template for AirportCode. If it doesn't exist, 
       nothing will be output.--> 
       <xsl:apply-templates select="AirportCode"/> 
       <!--Apply the template for AirportName. If it doesn't exist, 
       nothing will be output.--> 
       <xsl:apply-templates select="AirportName"/> 
      </CityNameComplete> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="AirportCode"> 
     <!--Output the value of AirportCode, surrounded by parenthesis and 
     preceded by a space.--> 
     <xsl:value-of select="concat(' (',.,')')"/> 
    </xsl:template> 

    <xsl:template match="AirportName"> 
     <!--Output the value of AirportName, preceded by a "space dash space".--> 
     <xsl:value-of select="concat(' - ',.)"/> 
    </xsl:template> 

</xsl:stylesheet> 
+0

哪裏有詳細的解釋如何工作?事實上,這個答案對未來的訪問者不是很有幫助。 –

+0

@ O.R.Mapper - 代碼非常簡單,我認爲它不是一個詳細的解釋。 OP在接受答案之前沒有任何問題,任何未來的訪問者也可能要求澄清。我添加了一些註釋來解釋代碼的功能。如果您有某個具體問題未包含在評論中,請告訴我。 –

+0

啊,好吧,往往不是互聯網的一個常數,原來的答案作者在未來的訪問者實際詢問某事時將不會再作出反應;-)更好的是立即提供解釋,然後再提供解釋。 –

1

將此嵌入到完整的XSLT中有多種方式,但假設您將<CityNameComplete>元素視爲原始Xml文檔中的<AirportName>元素的替換。

然後,關鍵是XSLT的<value-of>元素:

<xsl:template match="/Root/Item/AirportName"> 
    <CityNameComplete><xsl:value-of select="../CityName"/> (<xsl:value-of select="../AirportCode"/>) - <xsl:value-of select="."/></CityNameComplete> 
</xsl:template> 

這將在結果產生

<CityNameComplete>ANDORRA LA VELLA (ALV) - Andorra La Vella Hlpt</CityNameComplete> 

元素。

更新:

<xsl:template match="/Root/Item/AirportName"> 
    <CityNameComplete><xsl:text> </xsl:text><xsl:value-of select="../CityName"/> (<xsl:value-of select="../AirportCode"/>) - <xsl:value-of select="."/><xsl:text> </xsl:text></CityNameComplete> 
</xsl:template> 

結果:

<CityNameComplete> ANDORRA LA VELLA (ALV) - Andorra La Vella Hlpt </CityNameComplete> 

更新2:如果你真的要圍繞完成城市名稱的空白,在樣式表與<xsl:text> </xsl:text>添加它包括IATA代碼。

更新3:插入節點的替代解決方案是將其添加的模板<Item>元素:

<xsl:template match="/Root/Item"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
     <CityNameComplete><xsl:text> </xsl:text><xsl:value-of select="CityName"/> (<xsl:value-of select="AirportCode"/>) - <xsl:value-of select="AirportName"/><xsl:text> </xsl:text></CityNameComplete> 
    </xsl:copy> 
</xsl:template> 

請注意,您必須刪除您不想節點確切地得到你的輸出 - 因爲你沒有要求這樣做,因爲我不想混淆這個答案,所以我沒有包含任何關於如何去做的代碼。要做到這一點

+0

謝謝,Mapper,它工作完美! –

+0

我設法刪除了我不需要的節點,但我並不確定如何保留Root和Item。我的輸出是這樣的: ALV 安道爾 安道爾(ALV) - 安道爾Hlpt

+0

@OanaAnton:請參考在XSLT身份模板的說明中,例如這裏是:http://dev.ektron.com/kb_article.aspx?id=492它實質上是將源Xml文檔的全部內容複製到輸出中,但XSLT中的其他模板匹配的節點除外。 –

1

一種方法是建立在身份模板,並有一個額外的模板到項目匹配元素在其中,那麼你的輸出使用CONCAT功能CityNameComplete元素:

<xsl:template match="Item"> 
    <Item> 
    <xsl:apply-templates select="@*|node()"/> 
    <CityNameComplete> 
     <xsl:value-of select="concat(CityName, ' (', AirportCode, ') ', AirportName)"/> 
    </CityNameComplete> 
    </Item> 
</xsl:template> 

您還需要一個模板來忽略所有不想輸出的元素。在比CityCodeCITYNAME其他元素這種情況下,一切

<xsl:template match="Item/*[not(self::CityCode|self::CityName)]"/> 

以下是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="Item/*[not(self::CityCode|self::CityName)]"/> 

    <xsl:template match="Item"> 
     <Item> 
     <xsl:apply-templates select="@*|node()"/> 
     <CityNameComplete> 
      <xsl:value-of select="concat(CityName, ' (', AirportCode, ') ', AirportName)"/> 
     </CityNameComplete> 
     </Item> 
    </xsl:template> 

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

當適用於您的XML輸入,輸出以下

<Root> 
    <Item> 
    <CityCode>ALV</CityCode> 
    <CityName>ANDORRA LA VELLA</CityName> 
    <CityNameComplete>ANDORRA LA VELLA (ALV) Andorra La Vella Hlpt</CityNameComplete> 
    </Item> 
</Root> 
+0

+1更好的解決方案。 –