【问题标题】:xsl namespace uri transformationxsl 命名空间 uri 转换
【发布时间】:2019-03-11 06:35:38
【问题描述】:

给定一个已在命名空间中实施版本控制方案的 xml 文档,我可以应用什么 xslt 来转换所有 uri,将文档映射到新版本?

我不知道文档将使用哪些命名空间,也不知道文档中引用的组织方式。

例如

<a:add
    xmlns:a="urn:_2018_1.a" 
    xmlns:b="urn:_2018_1.b" 
    xmlns:c="urn:_2018_1.c"
    ....
>
...

<a:add
    xmlns:a="urn:_2019_1.a" 
    xmlns:b="urn:_2019_1.b" 
    xmlns:c="urn:_2019_1.c"
    ....
>
...

【问题讨论】:

  • 使用这样的命名空间的人应该在黎明时被枪杀,但我想如果每个人都正确设计他们的 XML,XSLT 将变得多余......
  • @MichaelKay 总是需要将为一个目的正确设计的 XML 转换为为另一个目的正确设计的另一个 XML。
  • @Chomah 你确定你需要这样做吗?将 nodes 从旧的命名空间转换为新的就足够了,并将其留给 XSLT 处理器来提供必要的命名空间声明。

标签: xml xslt


【解决方案1】:

在 XSLT 2 和 3 中,您可以使用 xsl:namespace 创建命名空间节点,所以

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="3.0">

<xsl:param name="old-ns-year" select="'2018'"/>
<xsl:param name="new-ns-year" select="'2019'"/>

<xsl:mode on-no-match="shallow-copy"/>

<xsl:template match="*">
    <xsl:element name="{name()}" namespace="{replace(namespace-uri(), $old-ns-year, $new-ns-year)}">
        <xsl:apply-templates select="namespace::*, @*, node()"/>
    </xsl:element>
</xsl:template> 

<xsl:template match="namespace::*">
    <xsl:namespace name="{name()}" select="replace(., $old-ns-year, $new-ns-year)"/>
</xsl:template>

<xsl:template match="@*">
    <xsl:attribute name="{name()}" namespace="{replace(namespace-uri(), $old-ns-year, $new-ns-year)}" select="."/>
</xsl:template>

</xsl:stylesheet>

应该给你一个想法,https://xsltfiddle.liberty-development.net/pPzifpe 它会转换

<a:add
    xmlns:a="urn:_2018_1.a" 
    xmlns:b="urn:_2018_1.b" 
    xmlns:c="urn:_2018_1.c"
>
</a:add>

进入

<a:add xmlns:a="urn:_2019_1.a" xmlns:b="urn:_2019_1.b" xmlns:c="urn:_2019_1.c">
</a:add>

使用 Saxon 9.8。

【讨论】:

  • 谢谢。 XSLT 2 和 3 是唯一现实的选择吗?我正在使用 Java,并且更愿意依靠内置的东西而不是添加额外的依赖项。
  • XSLT 1 没有 xsl:namespace 元素来构造新的名称空间,这是 XSLT 2 或 3 的主要功能,需要以通用和紧凑的方式进行这项工作。我不再习惯于用 XSLT 1 术语来思考,让我们等待 XSLT 1 爱好者会给你什么建议。
  • 如果您使用 Java 工作,那么使用已经有将近 20 年历史的 XSLT 版本真的没有什么借口了。
  • 事实上没有纯 XSLT 1.0 解决方案,但是有一个使用 XSLT 1.0 加上 node-set() 扩展的解决方案。要在 XSLT 1.0 中动态创建命名空间,首先使用 &lt;xsl:element name="yy:dummy" namespace="{$uri}/> 在该命名空间中构造一个元素节点,将其放入变量中,使用节点集扩展将变量转换为节点集,然后选择并复制命名空间节点使用&lt;xsl:copy-of select="xx:node-set($dummy)//namespace::yy"/&gt;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-24
  • 1970-01-01
相关资源
最近更新 更多