2017-06-11 49 views
1

我有下面的XML:XSLT:排序,重命名,並添加缺少的元素

<?xml version='1.0' encoding='UTF-8'?> 
    <order-data> 
     <addressRecord> 
      <address> 
       <resState>CA</resState> 
       <resStreetnum>1250</resStreetnum> 
       <resStreetname>CYPRESS ROAD</resStreetname> 
       <resPOBox/> 
       <resCity>SAN DIEGO</resCity> 
       <resAptNo>11B</resAptNo> 
       <resZip>92601</resZip> 
      </address> 
     </addressRecord> 
     <empAddressRecord> 
      <address> 
       <empCity>ALBUQUERQUE</empCity> 
       <empStreetnum>9874</empStreetnum> 
       <empStreetname>COYOTE TRAIL</empStreetname> 
       <empState>NM</empState> 
       <employer>ACME ROCKET COMPANY</employer> 
       <empZip>87104</empZip> 
      </address> 
     </empAddressRecord> 
    </order-data> 

我用下面的排序和重命名使用的地址元素在第二個應用程序(我有過爲了不控制

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" indent="yes" version="1.0" encoding="UTF-8"/> 

    <xsl:template match="text()"> 
     <xsl:value-of select="normalize-space(.)"/> 
    </xsl:template> 

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

    <!-- Rename element --> 

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

    <!-- Address Record --> 
    <xsl:template match="addressRecord/address | AddressRecord/address"> 
     <xsl:element name="Group"> 
      <xsl:apply-templates select="resStreetnum"/> 
      <xsl:apply-templates select="resStreetname"/> 
      <xsl:apply-templates select="resAptNo"/> 
      <xsl:apply-templates select="resPOBox"/> 
      <xsl:apply-templates select="resCity"/> 
      <xsl:apply-templates select="resState"/> 
      <xsl:apply-templates select="resZip"/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="address/resStreetnum"> 
     <xsl:element name="V1"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/resStreetname"> 
     <xsl:element name="V2"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/resAptNo"> 
     <xsl:element name="V3"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/resPOBox"> 
     <xsl:element name="V4"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/resCity"> 
     <xsl:element name="V5"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/resState"> 
     <xsl:element name="V6"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/resZip"> 
     <xsl:element name="V7"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 

    <!-- Employer and Address Record --> 
    <xsl:template match="empAddressRecord/address"> 
     <xsl:element name="Group"> 
      <xsl:apply-templates select="employer"/> 
      <xsl:apply-templates select="empStreetnum"/> 
      <xsl:apply-templates select="empStreetname"/> 
      <xsl:apply-templates select="empAptNo"/> 
      <xsl:apply-templates select="empPOBox"/> 
      <xsl:apply-templates select="empCity"/> 
      <xsl:apply-templates select="empState"/> 
      <xsl:apply-templates select="empZip"/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="address/employer"> 
     <xsl:element name="V1"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/empStreetnum"> 
     <xsl:element name="V2"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/empStreetname"> 
     <xsl:element name="V3"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/empAptNo"> 
     <xsl:element name="V4"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/empPOBox"> 
     <xsl:element name="V5"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/empCity"> 
     <xsl:element name="V6"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/empState"> 
     <xsl:element name="V7"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="address/empZip"> 
     <xsl:element name="V8"> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:element> 
    </xsl:template> 

</xsl:transform> 

這導致:在源XML元素)的

<?xml version="1.0" encoding="UTF-8"?> 
<order> 
    <addressRecord> 
    <Group> 
     <V1>1250</V1> 
     <V2>CYPRESS ROAD</V2> 
     <V3>11B</V3> 
     <V4/> 
     <V5>SAN DIEGO</V5> 
     <V6>CA</V6> 
     <V7>92601</V7> 
    </Group> 
    </addressRecord> 
    <empAddressRecord> 
    <Group> 
     <V1>ACME ROCKET COMPANY</V1> 
     <V2>9874</V2> 
     <V3>COYOTE TRAIL</V3> 
     <V6>ALBUQUERQUE</V6> 
     <V7>NM</V7> 
     <V8>87104</V8> 
    </Group> 
    </empAddressRecord> 
</order> 

產生的問題當t他傳入的源xml不提供缺少元素的空標記(注意<empAddressRecord>不包含<V4/><V5/>標記)。第二個應用程序不能很好地處理丟失的數據。

我正在尋找一種XSLT機制來創建空的<V1/>,<V2/>等標記,當源xml不提供空元素標記。我搜索了這個網站以及其他的解決方案,並嘗試了條件和其他機制,但目前爲止似乎沒有任何工作。

謝謝。

+0

那麼哪些元素在輸入中是可選的,你需要添加哪些元素?你僅限於XSLT 1.0嗎? –

+0

輸入中的所有元素都可以被認爲是可選的。我需要輸出包含所有''標記,無論有無數據。如果輸入包含一個空元素,即'',則會創建相應的空''標籤,但是如果輸入省略了空元素,則輸出將不會創建標籤,然後輔助應用程序結束放置數據在錯誤的地方。我僅限於XSLT 1.0。 – PerryC

+0

@PerryC怎麼樣'V8'?應該(還是可以)將它包含在第一個「Group」中? –

回答

1

的方法:

XSLT 1.0

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

<xsl:template match="/order-data"> 
    <order> 
     <xsl:apply-templates/> 
    </order> 
</xsl:template> 

<xsl:template match="addressRecord | empAddressRecord"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="addressRecord/address"> 
    <Group> 
     <V1> 
      <xsl:value-of select="resStreetnum"/> 
     </V1> 
     <V2> 
      <xsl:value-of select="resStreetname"/> 
     </V2> 
     <V3> 
      <xsl:value-of select="resAptNo"/> 
     </V3> 
     <V4> 
      <xsl:value-of select="resPOBox"/> 
     </V4> 
     <V5> 
      <xsl:value-of select="resCity"/> 
     </V5> 
     <V6> 
      <xsl:value-of select="resState"/> 
     </V6> 
     <V7> 
      <xsl:value-of select="resZip"/> 
     </V7> 
    </Group> 
</xsl:template> 

<xsl:template match="empAddressRecord/address"> 
    <Group> 
     <V1> 
      <xsl:value-of select="employer"/> 
     </V1> 
     <V2> 
      <xsl:value-of select="empStreetnum"/> 
     </V2> 
     <V3> 
      <xsl:value-of select="empStreetname"/> 
     </V3> 
     <V4> 
      <xsl:value-of select="empAptNo"/> 
     </V4> 
     <V5> 
      <xsl:value-of select="empPOBox"/> 
     </V5> 
     <V6> 
      <xsl:value-of select="empCity"/> 
     </V6> 
     <V7> 
      <xsl:value-of select="empState"/> 
     </V7> 
     <V8> 
      <xsl:value-of select="empZip"/> 
     </V8> 
    </Group> 
</xsl:template>   

</xsl:stylesheet> 
+0

這很完美!謝謝。 – PerryC

1

如果你可以移動到XSLT 2.0那麼你爲什麼不這樣做簡單,你可以像使用

<xsl:param name="default-elements"> 
    <address> 
     <employer/> 
     <empStreenum/> 
     <empStreetname/> 
     <empAptNo/> 
     <empPOBox/> 
     <empCity/> 
     <empState/> 
     <empZip/> 
    </address> 
</xsl:param> 

<!-- Employer and Address Record --> 
<xsl:template match="empAddressRecord/address"> 
    <Group> 
     <xsl:apply-templates 
      select=" 
      (employer, $default-elements/address/employer)[1], 
      (empStreetnum, $default-elements/address/empStreetnum)[1], 
      (empStreetname, $default-elements/address/empStreetname)[1], 
      (empAptNo, $default-elements/address/empAptNo)[1], 
      (empPOBox, $default-elements/address/empPOBox)[1], 
      (empCity, $default-elements/address/empCity)[1], 
      (empState, $default-elements/address/empState)[1], 
      (empZip, $default-elements/address/empZip)[1]" 
     /> 
    </Group> 
</xsl:template>