gpt4 book ai didi

具有动态命名空间的 XSLT 转换

转载 作者:行者123 更新时间:2023-12-01 23:26:09 26 4
gpt4 key购买 nike

我需要将一个 XML 文件转换为另一个 XML 文件,其中源文件的动态命名空间设置为 xmlns="whatever"。我的 XSLT 在文件中没有命名空间的情况下运行良好,但我没有得到带有命名空间的输出。如何将源文件的架构应用到目标文件?

感谢所有帮助并提前致谢!

编辑:

我正在尝试将命名空间 uri 复制到生成的文件中:

<xsl:param name="schema">
<xsl:value-of select="namespace-uri()" />
</xsl:param>

<xsl:element name="root" namespace="$schema">

我已经验证模式持有正确的值,但问题是程序似乎过于字面意思:

<root xmlns="$schema">

这是解决这个问题的正确方法吗?

编辑 x2:

我已经实现了 Alejandro 的建议:

<xsl:element name="root" namespace="{$schema}"/> 

这在大多数情况下都有效,除了我必须将 namespace 放在每个元素上,否则我会在结果中得到以下结构:

<root xmlns="NAMESPACE">
<foo xmlns="">

等等

除了将 namespace={$schema} 放在每一行之外,有没有办法用这个命名空间覆盖所有元素?赏金并接受最佳答案!

编辑 x3:更好的例子:

如果我这样做:

<xsl:element name="root" namespace="{namespace-uri()}>
<xsl:element name="foo">
<xsl:element name="bar">
<!--etc-->
</xsl:element>
</xsl:element>
</xsl:element>

我得到:

<root xmlns="NAMESPACE">
<foo xmlns="">
<bar>
<!--etc-->
</bar>
</foo>
<root>

我想让它们都在 namespace NAMESPACE 下,所以我这样做了:

<xsl:element name="root" namespace="{namespace-uri()}>
<xsl:element name="foo" namespace="{namespace-uri()}>
<xsl:element name="bar" namespace="{namespace-uri()}>
<!--etc-->
</xsl:element>
</xsl:element>
</xsl:element>

然而,这样的输入方式既丑陋又乏味。有没有更简单的方法来覆盖所有元素的 namespace ? (希望这能澄清我的需要)

最佳答案

假设您有这样的 XML 输入:

<root xmlns="survivors"> 
<louis/>
<francis/>
</root>

这意味着每个元素都在默认命名空间下,其 URI 是“survivors”。

正如 Welbog 所写,您可以选择 francis 元素:

/*/*[local-name()='francis']

/*[local-name()='root']/*[local-name()='francis']

但是,这也从这些 XML 输入中选择了 francis 元素:

<root xmlns="survivors" xmlns:n="no-survivors"> 
<louis/>
<n:francis/>
</root>

<root xmlns="survivors"> 
<louis/>
<francis xmlns="no-survivors"/>
</root>

您还可以使用一些命名空间 URI 来加强谓词。但是,哪一个?一个选项可以是根元素的默认命名空间,例如:

/*/*[local-name()='francis'][namespace-uri()=namespace-uri(/*)]

这肯定会使 XPath 表达式变得非常冗长。

在 XSLT 2.0 中,您可以使用 xsl:xpath-default-namespace 属性,例如:

<xsl:value-of select="/root/francis" xpath-default-namespace="survivors"/> 

但这对您的情况不利,因为您事先不知道 URI。

编辑:xsl:element 的属性是 AVT(属性值模板),因此您需要:

<xsl:element name="root" namespace="{$schema}"/> 

此外,我建议您将参数声明为字符串数据类型(不像现在的 RTF),例如:

<xsl:param name="schema" select="namespace-uri()"/> 

编辑 2:也许我不清楚。您不需要在所有情况下都使用 xsl:element/@namespace。根据您声明每个元素仅在一个默认 namespace 中,此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[local-name()='bar']">
<xsl:element name="newbar" namespace="{namespace-uri()}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

有了这个输入:

<root xmlns="whatever">
<foo/>
<bar/>
</root>

输出:

<root xmlns="whatever">
<foo></foo>
<newbar></newbar>
</root>

编辑 2:我向您展示了当您复制一个元素时,您也在复制扩展 QName 所需的命名空间。所以,如果想改变这个:

<root xmlns="whatever">
<foo/>
<bar/>
</root>

进入这个:

<root xmlns="whatever">
<foo>
<bar/>
</foo>
</root>

您可以使用此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="*[1]|following-sibling::*[1]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

关于具有动态命名空间的 XSLT 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3347047/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com