XSLT支持向后兼容性

时间:2015-02-25 19:37:42

标签: xml xslt

你有xml这样的东西:

 <q:foo
      xmlns:q="http://www.example.com/foo-1_0" xmlns:p="http://www.example.com/common/goo-1_0"
      xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.example.com/foo/foo-1_0.xsd">
      <p:payload>
        <p:var-list>
          <p:var>
            <p:key>key1</p:key>
            <p:value xsi:type="xs:string">string content</p:value>
          </p:var>
        </p:var-list>
      </p:payload>
    </q:foo>   

但是,编写它的人不知道文档命名空间的真实标识符不是http://www.example.com/foo- 1_0 ,而是http://www.example.com/foo- 1_1 即可。所以你需要一个样式表来更新网址。这就是xslt。

    <?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:old="http://www.example.com/foo-1_0"
  xmlns:q="http://www.example.com/foo-1_1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:oldc="http://www.example.com/common/goo-1_0" xmlns:p="http://www.example.com/common/goo-1_1">
  <xsl:output omit-xml-declaration="yes" indent="yes" />
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:namespace name="xs" select="'http://www.w3.org/2001/XMLSchema'" />
      <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@xsi:schemaLocation">
    <xsl:attribute name="xsi:{'schemaLocation'}">
          <xsl:value-of select="'http://www.example.com/foo/foo-1_1.xsd'"/>
      </xsl:attribute>
  </xsl:template>
  <xsl:template match="old:*">
    <xsl:element name="q:{local-name()}">
      <xsl:apply-templates select="node()|@*" />
    </xsl:element>
  </xsl:template>
  <xsl:template match="oldc:*">
    <xsl:element name="p:{local-name()}">
      <xsl:apply-templates select="node()|@*" />
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

并且输出符合预期。

<q:foo xmlns:q="http://www.example.com/foo-1_1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/foo/foo-1_1.xsd">
  <p:payload xmlns:p="http://www.example.com/common/goo-1_1">
    <p:var-list>
      <p:var>
        <p:key>key1</p:key>
        <p:value xsi:type="xs:string">string content</p:value>
      </p:var>
    </p:var-list>
  </p:payload>
</q:foo>

当我尝试验证输出xml时, xsi:type =“xs:string”由于未在输出xml中生成而未得到解析。请问任何人如何将以下内容包含在输出xml的 foo 元素中?

xmlns:xs="http://www.w3.org/2001/XMLSchema"

2 个答案:

答案 0 :(得分:1)

当您使用XSLT 2.0并且已经了解<xsl:namespace name="xs" select="'http://www.w3.org/2001/XMLSchema'" />时,您可以简单地将其放在将old:*映射到新元素的模板中,因为根元素是其中之一拥有名称空间声明:

<xsl:template match="old:*"> <xsl:element name="q:{local-name()}"> <xsl:namespace name="xs" select="'http://www.w3.org/2001/XMLSchema'" /> <xsl:apply-templates select="node()|@*" /> </xsl:element> </xsl:template>

答案 1 :(得分:0)

您可以使用xsl:copy-of复制元素上的范围内命名空间:

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:old="http://www.example.com/foo-1_0"
                xmlns:q="http://www.example.com/foo-1_1" 
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:oldc="http://www.example.com/common/goo-1_0" 
                xmlns:p="http://www.example.com/common/goo-1_1">
  <xsl:output omit-xml-declaration="yes" indent="yes" />

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

  <xsl:template name="CopyNamespaces">
    <xsl:copy-of select="namespace::*[. != 'http://www.example.com/foo-1_0' and 
                                      . != 'http://www.example.com/common/goo-1_0']"/>
  </xsl:template>

  <xsl:template match="@xsi:schemaLocation">
    <xsl:attribute name="{name()}">
      <xsl:text>http://www.example.com/foo/foo-1_1.xsd</xsl:text>
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="old:*">
    <xsl:element name="q:{local-name()}">
      <xsl:call-template name="CopyNamespaces" />
      <xsl:apply-templates select="node()|@*" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="oldc:*">
    <xsl:element name="p:{local-name()}">
      <xsl:call-template name="CopyNamespaces" />
      <xsl:apply-templates select="node()|@*" />
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

这是CopyNamespaces模板的一个额外花哨版本,它也复制了XSLT本身的命名空间,因此您可以在结果文档根元素上使用p命名空间声明在它之下:

<xsl:template name="CopyNamespaces">
  <xsl:copy-of select="(. | document('')/*)/namespace::*
                              [. != 'http://www.example.com/foo-1_0' and 
                               . != 'http://www.example.com/common/goo-1_0' and 
                               . != 'http://www.w3.org/1999/XSL/Transform']"/>
</xsl:template>