使用 XSL 根据 XML 的条件添加命名空间

Posted

技术标签:

【中文标题】使用 XSL 根据 XML 的条件添加命名空间【英文标题】:Getting Namespace added based on Condition for XML using XSL 【发布时间】:2019-03-04 05:14:26 【问题描述】:

我正在尝试根据条件将命名空间添加到 xml。但条件不起作用。有人可以帮忙吗?

输入 XML:

                    <n0:MainTag xmlns:n0='http://abc123.com' xmlns:prx='urn:testing.com' xmlns:soap-env='http://schemas.xmlsoap.org/soap/envelope/'>
                    <header>M</header>
                    <Data>
                        <Child>623471568753</Child>

                    </Data>
                </n0:MainTag>

输出 XML:

                    <?xml version="1.0" encoding="UTF-8"?>
                <ns0:MainTag xmlns:ns0="http://xyz987.com">
                    <header>M</header>
                    <Data>
                        <Child>623471568753</Child>
                    </Data>
                </n0:MainTag>

第二个输入: 输入 XML:

                <n0:DifferentTag xmlns:n0='http://abc123.com' xmlns:prx='urn:testing.com' xmlns:soap-env='http://schemas.xmlsoap.org/soap/envelope/'>
                <header>M</header>
                <Datum>
                    <Child>Test123</Child>

                </Datum>
            </n0:DifferentTag>

输出 XML:

                <n0:DifferentTag xmlns:ns0="http://QWR.com">
                <header>M</header>
                <Datum>
                    <Child>Test123</Child>

                </Datum>
            </n0:DifferentTag>

XSL 试过:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                                xmlns:ns0="http://xyz987.com">
<xsl:output encoding='UTF-8' indent='yes' method='xml'/>

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

<xsl:template match="MainTag">
    <xsl:element name="ns0:local-name()" namespace="http://xyz987.com">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>

<xsl:template match="MainTag">
    <xsl:element name="ns0:local-name()" namespace="http://QWR.com">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>

<xsl:template match="*/*">
    <xsl:element name="local-name()">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>
</xsl:stylesheet>

条件:检查源 XML 中的标签名称

【问题讨论】:

别忘了加上 XSL 试过了!另外,你能解释一下“条件”是什么吗?谢谢! 我已尝试添加 XSLT 代码,但未获得所需的输出。我们也期望不同的 xmls(超过 2 个),所以我只给出了两个输入 xmls。 【参考方案1】:

问题在于,在您的输入 XML 中,MainTagDifferentTag 都在“http://abc123.com”中,但您在 XSLT 中考虑到了这一点,因此它试图匹配无命名空间中的标签.

您需要在 XSLT 中声明前缀,并在匹配中使用它。

另外请注意,您当前的 XSLT 有两个匹配 MainTag 的模板,而其中一个可能应该匹配 DifferentTag

试试这个 XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:n0="http://abc123.com"
                              exclude-result-prefixes="n0">
<xsl:output encoding='UTF-8' indent='yes' method='xml'/>

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

<xsl:template match="n0:MainTag">
    <xsl:element name="ns0:local-name()" namespace="http://xyz987.com">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>

<xsl:template match="n0:DifferentTag">
    <xsl:element name="ns0:local-name()" namespace="http://QWR.com">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>

<xsl:template match="*/*">
    <xsl:element name="local-name()">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>
</xsl:stylesheet>

编辑:如果您真的不知道输入 XML 中的命名空间,请尝试使用此 XSLT...

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

<xsl:output encoding='UTF-8' indent='yes' method='xml'/>

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

<xsl:template match="*[local-name() = 'MainTag']">
    <xsl:element name="ns0:local-name()" namespace="http://xyz987.com">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>

<xsl:template match="*[local-name() = 'DifferentTag']">
    <xsl:element name="ns0:local-name()" namespace="http://QWR.com">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>

<xsl:template match="*/*">
    <xsl:element name="local-name()">
        <xsl:apply-templates select="@* | node()" />
    </xsl:element>
</xsl:template>
</xsl:stylesheet>

【讨论】:

但是是否可以不使用命名空间“abc123.com”来自源 XML,因为它可能因源系统不同而随 XML 不同而有所不同。 我已对我的答案进行了编辑,以展示您如何做到这一点。

以上是关于使用 XSL 根据 XML 的条件添加命名空间的主要内容,如果未能解决你的问题,请参考以下文章

XML 和 XSL 中的前缀命名空间处理由 XML 解析器返回错误

XML - 试图掌握命名空间 URI 的概念

XSL:避免将命名空间定义导出到生成的 XML 文档

如何从输出 xml 中删除命名空间?

如何使用 XSLT 替换命名空间中的元素?

XSL:删除命名空间前缀