使用XSLT从XSLT样式表中删除名称空间声明

时间:2012-09-17 18:20:03

标签: xslt xslt-1.0 xml-namespaces

我有一个类似于以下内容的XSLT样式表:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                  xmlns:XQHeaderFunc="java:com.sonicsw.xq.service.xform.HeaderExtension"
                  xmlns:saxon="http://saxon.sf.net/">

  <saxon:script language="java" implements-prefix="XQHeaderFunc" src="java:com.sonicsw.xq.service.xform.HeaderExtension" />

  <xsl:output indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="/">
    <xsl:variable name="processId" select="XQHeaderFunc:getProperty(XQHeaderFunc:new(),'processId',-1)" />
    <xsl:value-of select="XQHeaderFunc:setProperty(XQHeaderFunc:new(),'processId',string(@id),-1)"/>

    <root>
      <xsl:apply-templates />
    </root>

  </xsl:template>

  <!-- Other stuff -->

</xsl:stylesheet>

我想使用第二个XSLT样式表来转换此样式表,以删除与XQHeaderFunc和saxon命名空间有关的任何内容。有没有办法可以做到这一点?


我现在尝试了以下方法,它成功地处理了这些元素,但是命名空间声明似乎并不想消失。

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:XQHeaderFunc="java:com.sonicsw.xq.service.xform.HeaderExtension"
                xmlns:saxon="http://saxon.sf.net/"
                exclude-result-prefixes="XQHeaderFunc saxon">

  <xsl:param name="XQHeaderReplacement" />
  <xsl:variable name="apos">'</xsl:variable>

  <!-- Copy all nodes -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <!-- Remove saxon script tag -->
  <xsl:template match="saxon:script" />

  <!-- Remove elements with setProperty calls -->
  <xsl:template match="*[starts-with(@select, 'XQHeaderFunc:setProperty')]" />

  <!-- Replace getProperty calls with replacement value-->
  <xsl:template match="@select[starts-with(., 'XQHeaderFunc:getProperty')]">
      <xsl:attribute name="select">
        <xsl:value-of select="concat($apos, $XQHeaderReplacement, $apos)"/>
      </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

输出:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:XQHeaderFunc="java:com.sonicsw.xq.service.xform.HeaderExtension" 
                xmlns:saxon="http://saxon.sf.net/">

  <xsl:output indent="yes" omit-xml-declaration="yes" />

  <xsl:template match="/">
    <xsl:variable name="processId" select="''" />


    <root>
      <xsl:apply-templates />
    </root>

  </xsl:template>

  <!-- Other stuff -->

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:10)

我会添加

 exclude-result-prefixes="foo"

到你的

 <xsl:stylesheet>

元素。然后,如果可能,将省略foo的名称空间声明,即如果该名称空间中没有要输出的元素或属性。

仅供参考,原因是此行

<xsl:template match="xsl:stylesheet/@xmlns:foo" />`

抛出错误是因为输入文档中的xmlns:foo不是属性;这是一个伪属性。您的匹配模式要求匹配的是名为foo的属性,该属性位于与命名空间前缀xmlns对应的命名空间中。由于您尚未在样式表中声明名称空间前缀xmlns,因此会收到错误“未定义前缀xmlns。”

更新

我从你发布的输出(和我自己的测试)中看到exclude-result-prefixes在删除命名空间声明方面没有效果。

1)首先,我会问为什么这很重要。它不会更改输出XSLT中任何内容的命名空间。您是否只是出于美观原因试图将其删除?

2)查看<xsl:copy> exclude-result-prefixes不关注exclude-result-prefixes

  

实例化xsl:copy元素会创建当前节点的副本。   当前节点的命名空间节点将自动复制为   良好...

AFAICT,只有文字结果元素会根据<xsl:copy>省略命名空间节点。

在此基础上,我会尝试使用<xsl:element name="{name()}">或其某些变体替换您的身份模板中的<!-- Copy elements --> <xsl:template match="*" priority="-1"> <xsl:element name="{name()}"> <xsl:apply-templates select="node()|@*"/> </xsl:element> </xsl:template> <!-- Copy all other nodes --> <xsl:template match="node()|@*" priority="-2"> <xsl:copy /> </xsl:template> (对于元素)。然后,您需要为非元素节点使用单独的标识模板。

我用以下两个模板替换了您的身份模板:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output indent="yes" omit-xml-declaration="yes" />

   <xsl:template match="/">
      <xsl:variable name="processId" select="''" />
      <root>
         <xsl:apply-templates />
      </root>
   </xsl:template>

   <!-- Other stuff -->
</xsl:stylesheet>

这给了我认为的所需输出,没有多余的ns声明:

{{1}}

(为了清楚起见,我调整了空白。)