我有一个XML文档,我需要更改根节点。凭借我可以从网上获取的一点点知识,我能够看到我想要的东西,除了我的XML的子节点中有新的xmlns属性。我正在应用转换的XML看起来像:
<gmd:MD_Metadata xmlns="http://www.isotc211.org/2005/gmd"
xmlns:gco="http://www.isotc211.org/2005/gco"
xmlns:gmd="http://www.isotc211.org/2005/gmd"
xmlns:gmi="http://www.isotc211.org/2005/gmi"
xmlns:gml="http://www.opengis.net/gml"
xmlns:gmx="http://www.isotc211.org/2005/gmx"
xmlns:gsr="http://www.isotc211.org/2005/gsr"
xmlns:gss="http://www.isotc211.org/2005/gss"
xmlns:gts="http://www.isotc211.org/2005/gts"
xmlns:srv="http://www.isotc211.org/2005/srv"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.isotc211.org/2005/gmd
http://www.ngdc.noaa.gov/metadata/published/xsd/schema/gmd/gmd.xsd">
<gmd:language>
<gmd:LanguageCode
codeList="http://www.loc.gov/standards/iso639-2/php/code_list.php"
codeListValue="eng" codeSpace="ISO639-2"
>eng</gmd:LanguageCode>
</gmd:language>
......
</gmd:MD_Metadata>
我的XSLT看起来像这样:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:gmd="http://www.isotc211.org/2005/gmd"
xmlns:gco="http://www.isotc211.org/2005/gco"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gml="http://www.opengis.net/gml"
xmlns:gmi="http://www.isotc211.org/2005/gmi">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<gmi:MI_Metadata
xmlns="http://www.isotc211.org/2005/gmi"
xmlns:gco="http://www.isotc211.org/2005/gco"
xmlns:gmd="http://www.isotc211.org/2005/gmd"
xmlns:gmi="http://www.isotc211.org/2005/gmi"
xmlns:gml="http://www.opengis.net/gml"
xmlns:gmx="http://www.isotc211.org/2005/gmx"
xmlns:gsr="http://www.isotc211.org/2005/gsr"
xmlns:gss="http://www.isotc211.org/2005/gss"
xmlns:gts="http://www.isotc211.org/2005/gts"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://www.isotc211.org/2005/srv"
xsi:schemaLocation="http://www.isotc211.org/2005/gmi
http://www.ngdc.noaa.gov/metadata/published/xsd/schema.xsd" >
<xsl:for-each select="/*/node()|@*">
<xsl:copy-of select="." />
</xsl:for-each>
</gmi:MI_Metadata>
</xsl:template>
</xsl:stylesheet>
输出如下:
<gmi:MI_Metadata xmlns="http://www.isotc211.org/2005/gmi"
xmlns:gco="http://www.isotc211.org/2005/gco"
xmlns:gmd="http://www.isotc211.org/2005/gmd"
xmlns:gmi="http://www.isotc211.org/2005/gmi"
xmlns:gml="http://www.opengis.net/gml"
xmlns:gmx="http://www.isotc211.org/2005/gmx"
xmlns:gsr="http://www.isotc211.org/2005/gsr"
xmlns:gss="http://www.isotc211.org/2005/gss"
xmlns:gts="http://www.isotc211.org/2005/gts"
xmlns:srv="http://www.isotc211.org/2005/srv"
xmlns:v1="http://www.isotc211.org/2005/gmd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.isotc211.org/2005/gmi
http://www.ngdc.noaa.gov/metadata/published/xsd/schema.xsd">
<gmd:language xmlns="http://www.isotc211.org/2005/gmd">
<gmd:LanguageCode
codeList="http://www.loc.gov/standards/iso639-2/php/code_list.php"
codeListValue="eng" codeSpace="ISO639-2"
>eng</gmd:LanguageCode>
</gmd:language>
.......
</gmi:MI_Metadata>
我想避免在子节点的输出中使用 xmlns =“http://www.isotc211.org/2005/gmd”,有什么办法可以实现吗?当我将xslt的部分更改为:
时,我注意到了<xsl:template match="/">
<gmi:MI_Metadata xmlns="http://www.isotc211.org/2005/gmd" ....
xmlns消失但是头/节点不是客户端在输出中想要的!所以我不确定我能做什么。非常感谢您的见解,谢谢。
答案 0 :(得分:1)
无论exclude-result-prefixes
如何,xsl:copy-of
都会根据spec复制名称空间:
xsl:copy-of元素可用于将结果树片段插入到结果树中... [w]如果结果是节点集,则集合中的所有节点按文档顺序复制到结果树;复制元素节点会复制属性节点,命名空间节点以及元素节点的子节点以及元素节点本身......
因此,您需要自己进行(更多)复制。例如,这是解决方案的一部分,即复制元素的规则:
<xsl:template match="*" mode="copy" priority="1">
<xsl:element name="{name()}">
<xsl:apply-templates select="node()|@*" mode="copy"/>
</xsl:element>
</xsl:template>
然后正常复制内容
<xsl:template match="node()|@*" mode="copy">
<xsl:copy />
</xsl:template>
然后,在您的代码中,您可以执行
<xsl:for-each select="/*/node()|@*">
<xsl:apply-templates mode="copy" select="." />
</xsl:for-each>
答案 1 :(得分:0)
您可能想要阅读exclude-result-prefixes属性。
当然,它们具有gmd命名空间的默认命名空间声明,因为它们是从输入中复制的,这使得该命名空间成为默认命名空间(以及将其绑定到前缀gmd
)。我尝试将xsl:copy-of更改为更像传统的身份转换,以便您可以尝试覆盖子元素中的默认命名空间声明。
<xsl:copy>
<xsl:for-each
select="$ns-carrier/namespace::*[local-name() = 'xmlns']">
<xsl:copy/>
<xsl:for-each>
<xsl:for-each select="@*|node()">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:copy>
(未经测试,所以请加上一粒盐。)
可能有助于提醒自己(和客户端!),除非你正在做一些与命名空间绑定不同寻常的事情,然后对于任何相当不错的XML工具链,这是一个纯粹的装饰性问题而不是实质性的问题。 。 (也就是说,准备好告诉自己和你的客户,如果你不能设法让样式表做你想做的事情,那真的应该没关系。通过尝试让命名空间管理自动发生,XSLT的设计者有这很难手动完成。)