2011-12-26 34 views
2

我想要做一些像這樣的更復雜一點的Can you transform unordered xml to match an xsd:sequence order?。例如:使用XSLT對與正確模式匹配的元素進行排序XSD

<person> 
    <addressList> 
     <address> 
      <city>Chicago</city> 
      <state>IL</state> 
      <zip>41111</zip> 
     </address> 
     <address> 
      <state>MO</state> 
      <zip>64521</zip> 
      <city>Kansas City</city> 
     </address> 
    </addressList> 
    <lastname>The BFG</lastname> 
    <firstname>1234567890</firstname> 
</person> 

我沒有在模式控制,這符合前人的精力的模式,但是當我嘗試反序列化拋出一個錯誤...這樣的解決方案是使用XSLT轉換這種匹配XSD格式。我只是想得到相同的輸入,但以不同的順序,例如這樣的事情:

請注意城市在第二個地址,名字和姓氏是移動。

<person> 
    <lastname>The BFG</lastname> 
    <firstname>1234567890</firstname> 
    <addressList> 
     <address> 
      <city>Chicago</city> 
      <state>IL</state> 
      <zip>41111</zip> 
     </address> 
     <address> 
      <city>Kansas City</city> 
      <state>MO</state> 
      <zip>64521</zip> 
     </address> 
    </addressList> 
</person> 
+0

這是非常有用的http://stackoverflow.com/questions/1800593/transform-xml-into-specified-ordering-dtd-xsd – Jaider 2011-12-26 22:52:23

回答

2

基於以前的鏈接(Transform XML into specified ordering (DTD -> XSD)),只是我們必須做的更改是XSLT文件中的XML和根目錄的名稱(上衣者)和新的XSLT看起來像:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:my="my-namespace" 
    exclude-result-prefixes="my"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <my:person> 
     <my:lastname/> 
     <my:firstname/> 
     <my:addressList> 
      <my:address> 
       <my:city/> 
       <my:state/> 
       <my:zip/> 
      </my:address> 
     </my:addressList> 
    </my:person> 
    <xsl:template match="my:*"> 
    <xsl:param name="source"/> 
    <xsl:variable name="current-lookup-elem" select="current()"/> 
    <xsl:for-each select="$source/*[name()=local-name($current-lookup-elem)]"> 
     <xsl:copy> 
     <xsl:apply-templates select="$current-lookup-elem/*"> 
      <xsl:with-param name="source" select="current()"/> 
     </xsl:apply-templates> 
     <xsl:copy-of select="text()"/> 
     </xsl:copy> 
    </xsl:for-each> 
    </xsl:template> 
    <xsl:template match="/person"> 
    <xsl:apply-templates select="document('')/*/my:*"> 
     <xsl:with-param name="source" select="/"/> 
    </xsl:apply-templates> 
    </xsl:template> 
</xsl:stylesheet> 
2

這種轉變

<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="firstname|lastname"/> 

    <xsl:apply-templates select="addressList"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="address"> 
    <xsl:copy> 
    <xsl:apply-templates select="city"/> 
    <xsl:apply-templates select="state"/> 
    <xsl:apply-templates select="zip"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<person> 
    <addressList> 
     <address> 
      <city>Chicago</city> 
      <state>IL</state> 
      <zip>41111</zip> 
     </address> 
     <address> 
      <state>MO</state> 
      <zip>64521</zip> 
      <city>Kansas City</city> 
     </address> 
    </addressList> 
    <lastname>The BFG</lastname> 
    <firstname>1234567890</firstname> 
</person> 

產生想要的,正確的結果

<person> 
    <lastname>The BFG</lastname> 
    <firstname>1234567890</firstname> 
    <addressList> 
     <address> 
     <city>Chicago</city> 
     <state>IL</state> 
     <zip>41111</zip> 
     </address> 
     <address> 
     <city>Kansas City</city> 
     <state>MO</state> 
     <zip>64521</zip> 
     </address> 
    </addressList> 
</person> 

說明

  1. 身份規則(當沒有覆蓋)的每個節點 「原樣」 相匹配。

  2. 我們只覆蓋了元素的身份模板中,其子女需要在輸出改變順序/

  3. 要處理,爲了輸出節點是從他們的文檔順序不同,序列需要指定xsl:apply-templates指令,明確指定所需的新處理順序。