过滤名称空间并用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>

有一个仅用于筛选命名空间URI的XSLT代码:

<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. 未使用的命名空间的声明添加到根元素中。

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

如果您知道根元素的名称空间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>

注意:

这些都不应该是必要的。如上所述,名称空间前缀没有任何意义。未使用的名称空间声明是多余的。显然;"问题";是由接收端不一致的解析器引起的,修复它会更有效率。

最新更新