使用XSLT将XML文件转换为另一个XML文件

时间:2015-03-10 18:52:41

标签: xml xslt

我有一个简单的xml文件,我想使用XSLT进行转换。

第一个节点是架构(标头),以下节点是实际数据。请注意,数据中有一些缺少的字段。

<ex:file xmlns:ex="http://example.com">
  <ex:header>
    <ex:title>houseNumber</ex:title>
    <ex:title>street</ex:title>
    <ex:title>city</ex:title>
    <ex:title>state</ex:title>
  </ex:header>
  <ex:address>
    <ex:field>108</ex:field>
    <ex:field>Ridgewood Circle</ex:field>
    <ex:field>Rochester</ex:field>
    <ex:field>NY</ex:field>
  </ex:address>
  <ex:address>
    <ex:field/>
    <ex:field>W. Clark</ex:field>
    <ex:field>Springfield</ex:field>
    <ex:field>IL</ex:field>
  </ex:address>
</ex:file>

我们希望以两种方式转换此XML。 首先,我们想要使用&#34;标题&#34;中的信息。并且用这样的方式替换四个ex:field元素,我可以得到一个看起来像这样的XML:

<ex:file xmlns:ex="http://example.com">
  <ex:header>
    <ex:title>houseNumber</ex:title>
    <ex:title>street</ex:title>
    <ex:title>city</ex:title>
    <ex:title>state</ex:title>
  </ex:header>
  <ex:address>
    <ex:houseNumber>108</ex:houseNumber>
    <ex:street>Ridgewood Circle</ex:street>
    <ex:city>Rochester</ex:city>
    <ex:state>NY</ex:state>
  </ex:address>
  <ex:address>
    <ex:houseNumber/>
    <ex:street>W. Clark</ex:street>
    <ex:city>Springfield</ex:city>
    <ex:state>IL</ex:state>
  </ex:address>
</ex:file>

第二个转变是消除那些空元素:

<ex:file xmlns:ex="http://example.com">
  <ex:header>
    <ex:title>houseNumber</ex:title>
    <ex:title>street</ex:title>
    <ex:title>city</ex:title>
    <ex:title>state</ex:title>
  </ex:header>
  <ex:address>
    <ex:houseNumber>108</ex:houseNumber>
    <ex:street>Ridgewood Circle</ex:street>
    <ex:city>Rochester</ex:city>
    <ex:state>NY</ex:state>
  </ex:address>
  <ex:address>
    <ex:street>W. Clark</ex:street>
    <ex:city>Springfield</ex:city>
    <ex:state>IL</ex:state>
  </ex:address>
</ex:file>

请注意&#34; houseNumber&#34;在第二个&#34;记录&#34;走了。

我已多次浏览过XSLT教程(http://www.w3schools.com/xsl/default.asp),我不确定这是否可以实际完成。

提前感谢所有人。

1 个答案:

答案 0 :(得分:0)

以下转换解决了您的第一个问题。它是一个标识转换,带有一个额外的模板,用于指定应对每个ex:field元素执行的操作。

XSLT样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ex="http://example.com">

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

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

    <xsl:template match="ex:address">
        <xsl:copy>
            <xsl:for-each select="ex:field">
            <xsl:variable name="pos" select="position()"/>
                <xsl:element name="{concat('ex:',../../ex:header/ex:title[position() = $pos])}">
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:element>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

XML输出

<?xml version="1.0" encoding="utf-8"?>
<ex:file xmlns:ex="http://example.com">
   <ex:header>
      <ex:title>houseNumber</ex:title>
      <ex:title>street</ex:title>
      <ex:title>city</ex:title>
      <ex:title>state</ex:title>
   </ex:header>
   <ex:address>
      <ex:houseNumber>108</ex:houseNumber>
      <ex:street>Ridgewood Circle</ex:street>
      <ex:city>Rochester</ex:city>
      <ex:state>NY</ex:state>
   </ex:address>
   <ex:address>
      <ex:houseNumber/>
      <ex:street>W. Clark</ex:street>
      <ex:city>Springfield</ex:city>
      <ex:state>IL</ex:state>
   </ex:address>
</ex:file>

要同时排除空输入元素,最好将上述for-each重新配置为匹配ex:field元素的单独模板。然后,添加第二个匹配ex:field元素的模板,如果它们不包含任何文本。

XSLT样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ex="http://example.com">

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

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

    <xsl:template match="ex:field">
        <xsl:variable name="pos" select="position()"/>
                <xsl:element name="{concat('ex:',../../ex:header/ex:title[position() = $pos])}">
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:element>
    </xsl:template>

    <xsl:template match="ex:field[not(text())]"/>

</xsl:stylesheet>

最终XML输出

<?xml version="1.0" encoding="utf-8"?>
<ex:file xmlns:ex="http://example.com">
   <ex:header>
      <ex:title>houseNumber</ex:title>
      <ex:title>street</ex:title>
      <ex:title>city</ex:title>
      <ex:title>state</ex:title>
   </ex:header>
   <ex:address>
      <ex:houseNumber>108</ex:houseNumber>
      <ex:street>Ridgewood Circle</ex:street>
      <ex:city>Rochester</ex:city>
      <ex:state>NY</ex:state>
   </ex:address>
   <ex:address>
      <ex:street>W. Clark</ex:street>
      <ex:city>Springfield</ex:city>
      <ex:state>IL</ex:state>
   </ex:address>
</ex:file>