问题 如何通过在XSLT中编写单个语句来避免输出中的所有命名空间出现


我写了“exclude-result-prefixes”,然后我在输出中看到了名称空间出现的外观。

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:simple="Simple name space"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:tcm="http://www.tridion.com/ContentManager/5.0"
    xmlns:xh="http://www.w3.org/1999/xhtml"
    xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:transform-ext="urn:tridion:transform-ext"
    xmlns="http://www.w3.org/1999/xhtml"
    exclude-result-prefixes="#default simple xh">

实际产出

<strong xmlns="Simple name space">abcd
    <link xmlns="http://www.w3.org/1999/xhtml">
        <text>Header</text>
    </link>
</strong>

有没有任何方法可以通过编写单个语句来排除所有命名空间。

在这里我明确提到了

exclude-result-prefixes="#default simple xh"

如何避免xslt中的所有命名空间外观?


3533
2018-06-25 11:22


起源



答案:


exclude-result-prefixes 的属性 xsl:stylesheet,当指定为 "yes" 要求删除a的任何命名空间节点 中性结果要素 (仅)继承并且不定义文字结果元素的namespace-uri和prefix。

Markus Jarderot在回答中的以下陈述是错误的

“exclude-result-prefixes只删除了xmlns:foo =”“属性   结果的根标签。“

这是一个反例

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

 <xsl:template match="/">
  <z:x xmlns:z="z:z">
   <z:y/>
  </z:x>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于任何XML文档(未使用)时,结果为:

<z:x xmlns:z="z:z">
   <z:y/>
</z:x>

我们看到了

  1. 具有值(namespace-uri)“z:z”的命名空间的命名空间节点(和定义)不会从顶部元素中删除(Markus Jarderot称之为“根标记”)。

  2. 带前缀的命名空间 "z" 不会从任何文字元素中删除。

这显示了指定的简单事实 exclude-result-prefixes="yes" 如果命名空间不在LRE(文字结果元素)上,并且即使命名空间节点在LRE上但是正在定义该元素所属的命名空间,也无法删除它

为了从它所属的命名空间中删除元素,或从非LRE元素中删除命名空间,我们需要指定一些额外的处理。

一个例子是用以下内容替换传统的身份规则:

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

 <xsl:template match="node()[not(self::*)]">
     <xsl:copy>
       <xsl:apply-templates/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="*">
  <xsl:element name="{local-name()}">
   <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="@*">
  <xsl:attribute name="{local-name()}">
   <xsl:value-of select="."/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

上述转换将任何元素或属性替换为属于“无命名空间”的对应元素或属性。它的一个潜在用途是将具有默认命名空间的文档转换为没有这样的文档。

例如,应用于以下源XML文档时

<z:x xmlns:z="z:z">
    <z:y z:attr="someValue"/>
</z:x>

转型的结果是

<x>
   <y attr="someValue"/>
</x>

最后一个警告

如果应用于包含两个具有相同本地名称但属于两个不同名称空间的元素(或两个属性)的文档,则此转换可能有害 - 转换将这些转换为属于同一名称空间的元素(或属性)(没有命名空间)。


8
2018-06-25 12:37



使用XSL 2.0并使用其中任何一个复制元素时 <xsl:copy> 要么 <xsl:copy-of>,还有非常有用的 copy-namespaces 属性。将此设置为 no 复制元素时不复制命名空间。更详细的信息 zvon.org/comp/r/ref-XSLT_2.html#Attributes~copy-namespaces。 - Eiríkr Útlendi
@EiríkrÚtlendi,是的,这很有用。不幸的是,这不是XSLT 2.0的问题。这个答案可以在XSLT 1.0和XSLT 2.0 / 3.0中使用(可以在它之间移植) - Dimitre Novatchev
是的,这不适用于XSL 1.0。我遇到了这个问题并找到了你的解决方案,但由于技术限制,我一直在寻找另一种解决方法,并找到了解决方法 copy-namespaces 属性。为了完整起见,我添加了对未来寻求者的评论。 - Eiríkr Útlendi


答案:


exclude-result-prefixes 的属性 xsl:stylesheet,当指定为 "yes" 要求删除a的任何命名空间节点 中性结果要素 (仅)继承并且不定义文字结果元素的namespace-uri和prefix。

Markus Jarderot在回答中的以下陈述是错误的

“exclude-result-prefixes只删除了xmlns:foo =”“属性   结果的根标签。“

这是一个反例

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

 <xsl:template match="/">
  <z:x xmlns:z="z:z">
   <z:y/>
  </z:x>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于任何XML文档(未使用)时,结果为:

<z:x xmlns:z="z:z">
   <z:y/>
</z:x>

我们看到了

  1. 具有值(namespace-uri)“z:z”的命名空间的命名空间节点(和定义)不会从顶部元素中删除(Markus Jarderot称之为“根标记”)。

  2. 带前缀的命名空间 "z" 不会从任何文字元素中删除。

这显示了指定的简单事实 exclude-result-prefixes="yes" 如果命名空间不在LRE(文字结果元素)上,并且即使命名空间节点在LRE上但是正在定义该元素所属的命名空间,也无法删除它

为了从它所属的命名空间中删除元素,或从非LRE元素中删除命名空间,我们需要指定一些额外的处理。

一个例子是用以下内容替换传统的身份规则:

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

 <xsl:template match="node()[not(self::*)]">
     <xsl:copy>
       <xsl:apply-templates/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="*">
  <xsl:element name="{local-name()}">
   <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="@*">
  <xsl:attribute name="{local-name()}">
   <xsl:value-of select="."/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

上述转换将任何元素或属性替换为属于“无命名空间”的对应元素或属性。它的一个潜在用途是将具有默认命名空间的文档转换为没有这样的文档。

例如,应用于以下源XML文档时

<z:x xmlns:z="z:z">
    <z:y z:attr="someValue"/>
</z:x>

转型的结果是

<x>
   <y attr="someValue"/>
</x>

最后一个警告

如果应用于包含两个具有相同本地名称但属于两个不同名称空间的元素(或两个属性)的文档,则此转换可能有害 - 转换将这些转换为属于同一名称空间的元素(或属性)(没有命名空间)。


8
2018-06-25 12:37



使用XSL 2.0并使用其中任何一个复制元素时 <xsl:copy> 要么 <xsl:copy-of>,还有非常有用的 copy-namespaces 属性。将此设置为 no 复制元素时不复制命名空间。更详细的信息 zvon.org/comp/r/ref-XSLT_2.html#Attributes~copy-namespaces。 - Eiríkr Útlendi
@EiríkrÚtlendi,是的,这很有用。不幸的是,这不是XSLT 2.0的问题。这个答案可以在XSLT 1.0和XSLT 2.0 / 3.0中使用(可以在它之间移植) - Dimitre Novatchev
是的,这不适用于XSL 1.0。我遇到了这个问题并找到了你的解决方案,但由于技术限制,我一直在寻找另一种解决方法,并找到了解决方法 copy-namespaces 属性。为了完整起见,我添加了对未来寻求者的评论。 - Eiríkr Útlendi


exclude-result-prefixes 只是删除了 xmlns:foo="" 结果的根标记上的属性。标签仍然绑定到同一名称空间。由于标记没有任何匹配的前缀,因此使用默认命名空间。

如果要完全删除命名空间,可以使用以下样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="no"/>

    <xsl:template match="/|comment()|processing-instruction()">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

(资源: TEI维基


3
2018-06-25 11:40





exclude-result-prefixes属性将(在某些情况下)从输出中删除未使用的命名空间声明。它永远不会删除实际用于结果中的元素和属性的名称空间:也就是说,它永远不会更改元素和属性的名称以将它们放在不同的名称空间(或没有名称空间)中。如果希望元素不在命名空间中,则必须避免在生成它们时将它们放在命名空间中,无论是使用文字结果元素,xsl:element还是xsl:copy。


2
2018-06-25 14:25





尝试在样式表中使用它:

<stylesheet
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xhtml="http://www.w3.org/1999/xhtml"   ...etc >

我在里面有一些标签: xmlns="http://www.w3.org/1999/xhtml,所以我添加了这两行,现在好了。

这个消息来源帮助我: http://xmlplease.com/xhtmlxhtml


0
2018-04-17 14:45