【问题标题】:avoid adding xmlns attribute in xml response when applying XSLT应用 XSLT 时避免在 xml 响应中添加 xmlns 属性
【发布时间】:2013-06-01 17:50:51
【问题描述】:

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

【问题讨论】:

    标签: xslt xml-namespaces


    【解决方案1】:

    不管exclude-result-prefixesxsl:copy-of 都会复制命名空间,根据spec

    xsl:copy-of 元素可用于将结果树片段插入结果树...[当结果是节点集时,集合中的所有节点都按文档顺序复制到结果树;复制元素节点复制元素节点的属性节点、命名空间节点和子节点以及元素节点本身...

    因此,您需要自己进行(更多)复制。例如,这里有一个解决方案,复制元素的规则:

    <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>
    

    【讨论】:

    • 非常感谢 torazaburo 和 @C。 M. Sperberg-McQuee 感谢您的回复。我应用了 torazaburo 提供的 xslt 片段,并且能够摆脱子节点中的 xmlns 属性。我确实看到 xlink:type="simple" 附加到一些子元素,但我想我可以用谷歌搜索一些东西来处理它。再次感谢。
    【解决方案2】:

    您可能想阅读 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 的设计者已经手动操作非常困难。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-26
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      • 2012-01-14
      • 2016-03-25
      • 2012-08-24
      • 1970-01-01
      相关资源
      最近更新 更多