1

我有一个需要更改根节点的 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 消失了,但是头/根节点不是客户端在输出中想要的!所以我不确定我能做什么。您的见解将不胜感激,谢谢。

4

2 回答 2

1

无论如何exclude-result-prefixes,将根据规范xsl:copy-of复制命名空间:

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>
于 2013-06-06T04:15:16.927 回答
0

您可能想阅读 exclude-result-prefixes 属性。

当然,它们具有 gmd 命名空间的默认命名空间声明,因为它们是从使该命名空间成为默认命名空间的输入中复制的(并将其绑定到 prefix 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 的设计者已经手动操作非常困难。)

于 2013-06-06T01:08:39.950 回答