微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

过滤命名空间并用 XSLT 替换它们的前缀

如何解决过滤命名空间并用 XSLT 替换它们的前缀

如何仅保留所需的命名空间 URI(可能未使用)并将其所有前缀(基于前缀和 URI 列表)替换为 XSLT (1.0)?前缀和命名空间 URI 的原始组合可能会改变!

输入:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns4:node_0 
xmlns:ns6="http://a.com" 
xmlns:ns5="http://b.com" 
xmlns:ns8="http://c.com" 
xmlns:ns7="http://d.com" 
xmlns:ns2="http://e.com"
xmlns:ns4="http://f.com"
xmlns:ns3="http://g.com">
    <node_1 attr_1="attr_1_val" attr_2="attr_2_val">
        <ns4:node_11>node_11_val</ns4:node_11>
        <ns4:node_12 attr_1="attr_1_val" attr_2="attr_2_val">
            <ns2:node_121>node_121_val</ns2:node_121>
            <ns4:node_122>
                <node_1221>node_1221_val</node_1221>
                <ns3:node_1222>
                    <node_12221 attr_1="attr_1_val">
                        <node_122211>node_122211_val</node_122211>
                    </node_12221>
                </ns3:node_1222>
            </ns4:node_122>
            <node_123>
                <node_1231 attr_1="attr_1_val">
                    <node_12311>node_12311_val</node_12311>
                </node_1231>            
            </node_123>
        </ns4:node_12>
        <ns3:node_13>
            <node_131>
                <ns3:node_1311>node_1311_val</ns3:node_1311>
                <node_1312 attr_1="attr_1_val" attr_2="attr_2_val" attr_3="attr_3_val" attr_4="attr_4_val">
                    <ns3:node_13121/>
                </node_1312>
            </node_131>
        </ns3:node_13>
        <node_14/>
    </node_1>
    <ns4:node_2 attr_1="attr_1_val" attr_2="attr_2_val" attr_3="attr_3_val">
        <ns4:node_21>node_21_val</ns4:node_21>
    </ns4:node_2>
</ns4:node_0>

必需的命名空间 URI 及其前缀:

b_ns="http://b.com" 
e_ns="http://e.com"
f_ns="http://f.com"
g_ns="http://g.com"

所以需要的输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<f_ns:node_0 
xmlns:b_ns="http://b.com" 
xmlns:e_ns="http://e.com"
xmlns:f_ns="http://f.com"
xmlns:g_ns="http://g.com">
    <node_1 attr_1="attr_1_val" attr_2="attr_2_val">
        <f_ns:node_11>node_11_val</f_ns:node_11>
        <f_ns:node_12 attr_1="attr_1_val" attr_2="attr_2_val">
            <e_ns:node_121>node_121_val</e_ns:node_121>
            <f_ns:node_122>
                <node_1221>node_1221_val</node_1221>
                <g_ns:node_1222>
                    <node_12221 attr_1="attr_1_val">
                        <node_122211>node_122211_val</node_122211>
                    </node_12221>
                </g_ns:node_1222>
            </f_ns:node_122>
            <node_123>
                <node_1231 attr_1="attr_1_val">
                    <node_12311>node_12311_val</node_12311>
                </node_1231>            
            </node_123>
        </f_ns:node_12>
        <g_ns:node_13>
            <node_131>
                <g_ns:node_1311>node_1311_val</g_ns:node_1311>
                <node_1312 attr_1="attr_1_val" attr_2="attr_2_val" attr_3="attr_3_val" attr_4="attr_4_val">
                    <g_ns:node_13121/>
                </node_1312>
            </node_131>
        </g_ns:node_13>
        <node_14/>
    </node_1>
    <f_ns:node_2 attr_1="attr_1_val" attr_2="attr_2_val" attr_3="attr_3_val">
        <f_ns:node_21>node_21_val</f_ns:node_21>
    </f_ns:node_2>
</f_ns:node_0>

一个 XSLT 代码仅用于过滤命名空间 URI:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">            
           <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
            <xsl:strip-space elements="*"/>
            <xsl:template match="*">
                <xsl:element name="{name()}" namespace="{namespace-uri()}">
                    <xsl:copy-of select="namespace::*[
                     .='http://b.com'
                     or .='http://e.com'
                     or .='http://f.com'
                     or .='http://g.com"/>
                    <xsl:copy-of select="@*"/>
                    <xsl:apply-templates/>
                </xsl:element>
            </xsl:template>
</xsl:stylesheet>

编写完整的代码非常困难,因为对 XSLT 的经验很少。
提前谢谢!

解决方法

您在这里有两个独立的任务:

  1. 用给定 XML 的元素替换使用的命名空间的前缀;

  2. unused 命名空间的声明添加到根元素。

第一个任务非常简单,因为根据定义前缀并不重要。您需要做的就是使用您想要的前缀声明命名空间,然后使用新前缀重命名相应命名空间中的元素。

如果 - 正如您在评论中所说 - 您知道根元素的命名空间 URI,那么第二个任务可能很简单。然后,您可以将样式表中的命名空间声明复制到该命名空间中的元素(并希望处理器足够聪明,只执行一次):

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:b_ns="http://b.com" 
xmlns:e_ns="http://e.com"
xmlns:f_ns="http://f.com"
xmlns:g_ns="http://g.com">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="b_ns:*">
    <xsl:element name="b_ns:{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="e_ns:*">
    <xsl:element name="e_ns:{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<!-- this matches the root element -->
<xsl:template match="f_ns:*">
    <xsl:element name="f_ns:{local-name()}">
        <xsl:copy-of select="document('')/xsl:stylesheet/namespace::*[not(name()='xsl')]"/>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="g_ns:*">
    <xsl:element name="g_ns:{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="*">
    <xsl:element name="{name()}" namespace="{namespace-uri()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

注意:

这些都不是必要的。如上所述,名称空间前缀没有意义。未使用的命名空间声明是多余的。显然,这个“问题”是由接收端不符合标准的解析器引起的 - 解决这个问题会更有效率。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。