XSLT中的动态命名空间映射

时间:2014-01-15 00:24:15

标签: xml xslt xpath

I Have a requirement to do a transformation mapping for input xml for which the namespace can change in future.

If I define my input XML with namespace: xmlns:ns1="http://xmlns.sample.com.au/emprec/v1

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
        <soap:Body>
                <ns1:EmpRecord xmlns:ns1="http://xmlns.sample.com.au/emprec/v1">
                        <ns1:firstname>firstname</ns1:firstname>
                        <ns1:lastname>lastname</ns1:lastname>
                        <ns1:address>
                            <ns1:unit>1</n1:unit>
                            <ns1:street>st</ns1:street>
                            <ns1:suburb>suburb</ns1:suburb>
                        </ns1:address>
        </ns1:EmpRecord>
    </soap:Body>
</soap:Envelope>

and my XSLT as

<xsl:stylesheet version="1.0"
                xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20"
                xmlns:oraext="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.ExtFunc"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                xmlns:ns1="http://xmlns.sample.com.au/emprec/v1"
                xmlns:ns2="http://xmlns.sample.com.au/transformtotarget/v1"
                xmlns:ora="http://schemas.oracle.com/xpath/extension"
                exclude-result-prefixes="xsi xsl xsd wsdl ns1 xp20">

  <xsl:template match="/">
    <ns2:EMPLOYEES>
      <ns2:firstname>
        <xsl:value-of select="/ns1:EmpRecord/ns1:firstname"/>
      </ns2:firstname>
      <ns2:suburb>
         <xsl:value-of select="/ns1:EmpRecord/ns1:address/ns1:suburb"/>
      </ns2:suburb>
    </ns1:EMPLOYEES>
  </xsl:template>
</xsl:stylesheet>

只要XML的命名空间为http://xmlns.sample.com.au/emprec/v1,上面的XSLT就可以正常工作 如果将来我的命名空间更改,我如何使用相同的xslt? 我们可以说:http://xmlns.sample.com.au/emprec/v2

我不希望在xpath中映射时使用前缀命名空间,我希望它是动态的。 我曾尝试使用local-name()函数,但它可以工作,但不确定如果我有大量有效负载会对性能产生什么影响

  <ns2:suburb>
         <xsl:value-of select="/*[local-name()='EmpRecord'/*[local-name()='address'/*[local-name()='suburb'"/>
      </ns2:suburb>

上面的映射工作正常,但是如果我的xpath很长,这将是性能方面的推荐方法,有没有更好的方法来实现这个?

请帮忙。

3 个答案:

答案 0 :(得分:1)

“命名空间将来可能会发生变化”:人们普遍认为,这不是一个好的政策。更改名称空间具有很高的破坏性,这样做的成本几乎总是超过收益。所以人们最终没有这样做,即使他们原本打算这样做。 (我不知道为什么W3C会在其命名空间URI中放置一年。可能有人打算在此时更容易更改。但事实并非如此,而是这些命名空间永远存在,并且及时冻结。)

我的建议是,如果你想编写一个处理多个输入词汇表的样式表(你的问题就是这个问题的一个特例)就是为每个词汇表编写一个预处理阶段,规范化XML以使用单个词汇表。然后,您不必在整个代码中处理各种变体,而是在一个模块中完成这项工作,并且可以编写“真正的”转换而不必担心这个额外的问题。

你在没有让我们确信它是至关重要的情况下询问表现。代码的可维护性通常更为重要。但是,既然你问:性能取决于你使用的产品。如果您使用的是Saxon,那么搜索路径表达式中静态显示的名称比搜索动态提供的字符串更有效。

答案 1 :(得分:0)

性能将取决于您正在使用的XSLT引擎的实现细节,但是使用*然后添加谓词以通过local-name()限定它的方法是XSLT和XPath 1.0最好的方法。给你。

2.0版本的规范允许使用前缀为:*和*:localname。

的部分通配符

但是,命名空间名称(URI)确实不应该具有“在将来从源头进行更改”的重大风险。这是您正在处理的文档类型定义的一部分。改变它使它成为一种不同类型的文件。

答案 2 :(得分:-1)

如果我有多个使用给定命名空间的样式表,并且我无法控制的人强迫我更改该命名空间,我会打开一个文本编辑器,并使用该命名空间对我的所有样式表执行批量查找/替换(之后)首先支持他们,当然)。这是一次性操作,一旦完成,您可以恢复正常,而不必担心持续的性能影响。