【问题标题】:Transforming an XML file to another XML file using XSLT使用 XSLT 将 XML 文件转换为另一个 XML 文件
【发布时间】:2015-03-10 18:52:41
【问题描述】:

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

第一个节点是schema(header),后面的节点是实际数据。请注意,数据中有一些缺失的字段。

<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。 首先,我们要使用“标题”中的信息并替换四个 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>

请注意,第二个“记录”中的“houseNumber”不见了。

我已经多次阅读 XSLT 教程 (http://www.w3schools.com/xsl/default.asp),但我不确定这是否真的可以做到。

在此先感谢大家。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    以下转换解决了您的第一个问题。它是一种身份转换,带有一个额外的模板,用于指定应该对每个 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> 
    

    【讨论】:

      猜你喜欢
      • 2019-04-11
      • 2012-04-21
      • 1970-01-01
      • 1970-01-01
      • 2014-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多