2017-10-06 46 views
0

我有一個輸入XML,需要使用XSLT 2.0進行轉換。我需要添加缺少的節點,然後對包含添加的新節點進行排序

這裏是我的XML輸入

<root> 
     <person> 
      <LastName>yyyyy</LastName> 
      <FirstName>xxxx</FirstName> 
      <profession>IT/xx</profession> 
      <area>0000</area> 
      <email>[email protected]</email> 
      <Address>aaaaaaaaa,bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeee</Address> 
      <sex>male</sex> 
     </person> 
     </root> 

我輸入XML缺少一些節點。例如(移動,根據xsd強制執行的國家)。現在,我需要添加這兩個節點(作爲空節點),然後我需要排序包括這兩個節點。

排序應該是:名字,姓氏,電子郵件,性別,職業,移動,地址,地區,國家;

最終輸出的XML應該是:

<root> 
     <person> 
      <FirstName>xxxx</FirstName> 
      <LastName>yyyyy</LastName> 
      <email>[email protected]</email> 
      <sex>male</sex> 
      <profession>IT/xx</profession> 
      <mobile/> 
      <Address>aaaaaaaaa,bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeee</Address> 
      <area>0000</area> 
      <country/> 
     </person> 
     </root> 

我用下面的XSLT嘗試:

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

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

    <xsl:param name="pOrderedNames" select="'FirstName,LastName,email,sex,profession,mobile,Address,area,country'"/> 

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

    <xsl:template match="person[not(./country)]" mode="country"> 
     <xsl:element name="country" /> 
    </xsl:template> 

    <xsl:template match="person[not(./mobile)]" mode="mobile"> 
     <xsl:element name="mobile" /> 
    </xsl:template> 

    <xsl:template match="*" mode="sorter"> 
     <xsl:copy> 
      <xsl:apply-templates> 
       <xsl:sort data-type="number" select="string-length(substring-before($pOrderedNames,concat(',',name(),',')))"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="person"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()"/> 
      <xsl:apply-templates select="self::node()" mode="mobile"/> 
      <xsl:apply-templates select="self::node()" mode="country"/> 
      <xsl:apply-templates select="self::node()" mode="email"/> 
      <xsl:apply-templates select="self::node()" mode="sex"/>  
      <xsl:apply-templates select="self::*" mode="sorter"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

並與上述XSLT是越來越如下轉變:

<root> 
    <person> 
     <LastName>yyyyy</LastName> 
     <FirstName>xxxx</FirstName> 
     <profession>IT/xx</profession> 
     <area>0000</area> 
     <email>[email protected]</email> 
     <Address>aaaaaaaaa,bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeee</Address> 
     <sex>male</sex> 
     <mobile/> 
     <country/>yyyyyxxxxIT/[email protected],bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeeemaleyyyyyxxxxIT/[email protected],bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeeemale<person> 
     <FirstName>xxxx</FirstName> 
     <LastName>yyyyy</LastName> 
     <email>[email protected]</email> 
     <sex>male</sex> 
     <profession>IT/xx</profession> 
     <Address>aaaaaaaaa,bbbbbbbbbbbb,cccccccccc,dddddddddd,eeeeeeee</Address> 
     <area>0000</area> 
     </person> 
    </person> 
</root> 

請有人可以幫我解決這個問題。

在此先感謝。

+0

請說明您爲編寫XSLT所付出的努力。這是一個簡單的轉換,可以通過XSLT基礎知識來實現​​。 –

+0

你好Aniket,謝謝你的回覆。我已經包含了我嘗試過的XSLT。我得到的結果幾乎是靠近,但一些重複的數據在輸出xml中。你可以請看看它。 – krishh

+0

你好Aniket,它工作時,我沒有標記在輸入XML,但如果標記存在,那麼它不起作用。我在下面添加了詳細信息,請你幫幫我。 – krishh

回答

0

這裏是你的方法的適應它創建與模板的新元素,並通過包裝各種應用模板爲perform-sort對其進行排序:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> 

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

    <xsl:param name="pOrderedNames" 
     select="'FirstName,LastName,email,sex,profession,mobile,Address,area,country'"/> 
    <xsl:param name="pNameOrder" select="tokenize($pOrderedNames, ',')"/> 

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

    <xsl:template match="person" mode="country"> 
     <country/> 
    </xsl:template> 

    <xsl:template match="person" mode="mobile"> 
     <mobile/> 
    </xsl:template> 

    <xsl:template match="person"> 
     <xsl:copy> 
      <xsl:perform-sort> 
       <xsl:sort select="index-of($pNameOrder, local-name())"/> 
       <xsl:apply-templates select="*"/> 
       <xsl:apply-templates select=".[not(country)]" mode="country"/> 
       <xsl:apply-templates select=".[not(mobile)]" mode="mobile"/> 
      </xsl:perform-sort> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

我不知道創造了新的元素,你需要一個模板和一個模式,一個簡單的<xsl:if test="not(mobile)"><mobile/></xsl:if>就足夠了,但使用模式是一種可能的方式。

+0

嗨馬丁,謝謝你的回覆。它工作時,我沒有在輸入xml 標記,但如果標記存在,那麼它不起作用。我在下面添加了細節。你可以幫我嗎。提前致謝。 – krishh

+0

@krishh,我已經編輯了答案,並將代碼更改爲僅在person元素不存在時將「應用模板」應用於「person」元素本身,這應該可以避免遇到的問題,簡單地創建「xsl:if」測試中的新元素。 –