如何从它们所属的非空名称空间中删除名称?

时间:2010-12-02 04:58:50

标签: xslt

我想使用xslt转换输入xml文件,以更改可以出现在xml树的不同位置的特定元素的名称。

我有一个像下面这样的xml,

 <catalog>
 <cd>
  <ost:title>Empire Burlesque</ost:title>
  <artist>Bob Dylan</artist>
  <country>USA</country>
  <company>
     <ost:name>Columbia<ost:name>
  </company>
  <price>10.90</price>
  <year>1985</year>
 </cd>
</catalog>

我想从所有元素中删除所有'ost:'前缀,并保留其他所有内容,因为它使用的是xslt。一个示例代码将不胜感激。

2 个答案:

答案 0 :(得分:2)

在您的示例中,您似乎没有其他名称空间而不是您要删除的名称空间。所以,这是一个XSLT样式表的示例,它从元素中删除所有名称空间(而不仅仅是ost:)。

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- identity template: copy everything as is... -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- ... except for elements, 
       create a similarly named element without a namespace -->
  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

它使用identity transformation按原样复制所有内容,但会覆盖元素以创建具有相同本地名称但没有名称空间的元素。

如果您只想删除ost:命名空间,可以包含该命名空间的命名空间声明,并将后一个模板更改为匹配ost:*

答案 1 :(得分:0)

这种转变是最普遍的。它从全局参数中指定的命名空间中删除所有元素和属性。它还会删除作为其中一个命名空间的所有命名空间节点

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <my:delNs>
   <ns>some:namespace1</ns>
   <ns>some:namespace3</ns>
 </my:delNs>

 <xsl:variable name="vdelNS"
  select="document('')/*/my:delNs/*"/>

 <xsl:template match="*">
  <xsl:element name="{name()}" namespace="{namespace-uri()}">
   <xsl:copy-of select="namespace::*[not(.=$vdelNS)]"/>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="@*">
  <xsl:copy-of select="."/>
 </xsl:template>

 <xsl:template priority="10" match=
 "*[namespace-uri()=document('')/*/my:delNs/*]">

  <xsl:element name="{local-name()}">
   <xsl:copy-of select="namespace::*[not(.=$vdelNS)]"/>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match=
 "@*[namespace-uri()=document('')/*/my:delNs/*]">
   <xsl:attribute name="{local-name()}">
    <xsl:value-of select="."/>
   </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档(基于提供的,但已更正为格式良好并扩展为包含3个名称空间及其中的元素和属性):

 <catalog xmlns:ost="some:namespace1"
  xmlns:x="some:namespace2"
  xmlns:y="some:namespace3">
 <cd>
  <ost:title>Empire Burlesque</ost:title>
  <y:artist>Bob Dylan</y:artist>
  <country>USA</country>
  <company ost:type="big">
     <ost:name>Columbia</ost:name>
  </company>
  <x:price>10.90</x:price>
  <year>1985</year>
 </cd>
</catalog>

生成了想要的结果

<catalog xmlns:x="some:namespace2">
   <cd>
      <title>Empire Burlesque</title>
      <artist>Bob Dylan</artist>
      <country>USA</country>
      <company type="big">
         <name>Columbia</name>
      </company>
      <x:price>10.90</x:price>
      <year>1985</year>
   </cd>
</catalog>

<强>解释

  1. 前两个模板几乎等同于身份规则,但它们不会复制 <my:delNs>中指定的命名空间的命名空间节点。

  2. 最后两个模板适用于属于 <my:delNs>下列出的命名空间的所有元素和属性。仅在这两个模板中,名称实际上仅更改为本地名称。