XSLT:排序,重命名和添加缺少的元素

时间:2017-06-11 15:14:28

标签: xml xslt

我有以下XML:

<?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中元素的顺序):

<?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 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>

如果传入的源xml没有为缺少的元素提供空标记,则会出现问题(注意<empAddressRecord>不包含<V4/><V5/>标记)。第二个应用程序不能很好地处理丢失的数据。

当源xml不提供空元素标记时,我正在寻找一种XSLT机制来创建空<V1/><V2/>等标记。我已经搜索过这个网站以及其他人的解决方案,并尝试过条件和其他机制,但到目前为止似乎没有任何工作。

感谢。

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分: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>
相关问题