简体   繁体   English

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

[英]Transforming an XML file to another XML file using XSLT

I have a simple xml file I would like to transform using XSLT. 我有一个简单的xml文件,我想使用XSLT进行转换。

The first node is the schema(header), the following nodes are the actual data. 第一个节点是架构(头),接下来的节点是实际数据。 Notice that there are some missing fields in the data. 请注意,数据中缺少一些字段。

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

We would like to transform this XML in two ways. 我们想以两种方式转换这个XML。 First, we want to use the information in the "header" and substitute the four ex:field elements, in such a way I can get an XML that looks like: 首先,我们要使用“标题”中的信息并替换四个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>

The second transformation is to eliminate those empty element: 第二种转换是消除那些空元素:

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

Notice that the "houseNumber" in the second "record" is gone. 请注意,第二个“记录”中的“ houseNumber”已消失。

I have gone through the XSLT tutorial ( http://www.w3schools.com/xsl/default.asp ) several times and I am not sure if this can be actually done. 我已经多次阅读XSLT教程( http://www.w3schools.com/xsl/default.asp ),但不确定是否可以实际完成。

Thanks in advance to all. 在此先感谢所有人。

The following transformation solves your first problem. 以下转换解决了您的第一个问题。 It is an identity transform with one additional template that specifies what should be done to each ex:field element. 这是一个带有一个附加模板的身份转换,该模板指定了对每个ex:field元素应该执行的操作。

XSLT Stylesheet 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 Output 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>

To also exclude empty input elements, it is better to reformulate the above for-each as a separate template matching ex:field elements. 要还排除空的输入元素,最好将上述for-each重新编写for-eachex:field元素匹配的单独模板。 Then, add a second template that matches ex:field elements if they do not contain any text. 然后,添加第二个与ex:field元素匹配的模板(如果它们不包含任何文本)。

XSLT Stylesheet 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>

Final XML Output 最终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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM