【问题标题】:How to use xslt to add namespaces to xml如何使用 xslt 将命名空间添加到 xml
【发布时间】:2010-12-22 02:07:59
【问题描述】:

我有一个定义为契约优先的 SOAP Web 服务——请求和响应 xml 由使用许多不同名称空间的 xsd 定义,并且在 xsds 中定义了 100 多个元素。但是,Web 服务调用了不使用 xml 中的命名空间的遗留层。因此,我在 Web 服务和使用 xslt 转换请求和响应 xml 的遗留层之间有一个转换层。在转换层的途中使用 xslt 从请求 xml 中去除命名空间前缀,这工作正常,因为只有少量命名空间前缀要匹配。

但是,在退出的过程中,我需要一个 xslt,它将命名空间前缀添加回响应中,但我不确定如何执行此操作。响应可能包含几十种不同的元素类型;它可能属于 xsds 中几个不同的命名空间之一。例如,我可能会有这样的回应:

<order>
  <item name="table"/>
  <customer name="jim"/>
</order>

我需要把它转换成:

<order 
  xmlns:types1="http://types1.company.com" xmlns:types2="http://types2.company.com">
  <types1:item name="table"/>
  <types2:customer name="jim"/>
</order>

做到这一点的唯一方法是在 xslt 中有一个大表来匹配响应中的元素名称(例如,“item”、“customer”)与应该使用的前缀吗?

或者将一些在 xsd 中加载为 xml 的代码进行修正,然后将响应元素与 xsd 中的元素进行匹配并以这种方式派生正确的命名空间会更好吗?

【问题讨论】:

  • 如果同名出现在多个命名空间中,如何确定使用哪个命名空间?
  • 是的,这是一个潜在的问题,我还不知道这是否是我们拥有的 xsds 的实际问题。如果确实发生了,我可能也会求助于检查祖先元素,直到我得到一个唯一的匹配。

标签: xml web-services xslt


【解决方案1】:

我认为这样的事情可以完成这项工作:

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

  <!-- the identity template to copy everything as it is -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
  </xsl:template>

  <!-- elements are re-created with a namespace -->
  <xsl:template match="*">

    <xsl:variable name="ns-uri">
      <xsl:choose>
        <xsl:when test="name() = 'item' and name(..) = 'order'">
          <xsl:text>http://types1.company.com</xsl:text>
        </xsl:when>
        <xsl:when test="name() = 'customer' and name(..) = 'order'">
          <xsl:text>http://types2.company.com</xsl:text>
        </xsl:when>
        <!-- otherwise: nothing -->
      </xsl:choose>
    </xsl:variable>

    <!-- create the element with the correct namespace -->    
    <xsl:element name="{name()}" namespace="{$ns-uri}">
      <xsl:apply-templates select="node() | @*" />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

我的输出是:

<order>
  <item name="table" xmlns="http://types1.company.com"></item>
  <customer name="jim" xmlns="http://types2.company.com"></customer>
</order>

这就是你所拥有的,只是没有前缀。信息集完全相同。

【讨论】:

  • 这看起来很有希望。我创建了另一个变量来保存前缀,另一个 xsl:choose 根据匹配的 name() 设置前缀。
猜你喜欢
  • 2011-12-09
  • 2014-07-23
  • 1970-01-01
  • 1970-01-01
  • 2017-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多