【问题标题】:How can I force an XSLT result tree to serialize with a particular default namespace?如何强制 XSLT 结果树使用特定的默认命名空间进行序列化?
【发布时间】:2009-08-16 14:42:36
【问题描述】:

我正在尝试从文档中去除命名空间限定符,同时将文档命名空间保留为默认值:

<foo:doc xmlns:foo='somenamespace'>
    <foo:bar />
</foo:doc>

<doc xmlns='somenamespace'>
    <bar/>
</doc>

(我知道,这是没有意义的,但是我们的客户端并没有获取 XML,而是使用字符串比较来查找文档中的信息。)

我在这里使用 Java 的 JAXP Transformer API 来完成我的工作。我可以用这个样式表去掉 all 命名空间信息,但我想强制序列化不带前缀:

<?xml version='1.0' encoding='UTF-8'?> 
    <xsl:stylesheet 
          xmlns:xsl='http://www.w3.org/1999/XSL/Transform'  
          xmlns:xs='http://www.w3.org/2001/XMLSchema' 
          exclude-result-prefixes='xs' 
          version='2.0'> 

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

      <xsl:template match='@*|node()'> 
        <xsl:copy> 
          <xsl:apply-templates select='@*|node()' /> 
        </xsl:copy> 
      </xsl:template> 

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

我该怎么做?

【问题讨论】:

  • 您是否有机会帮助您的客户正确处理 XML?也许您可以编写一个他们可以使用的库?我认为您允许他们继续认为这就是 XML 的意义所在,这对他们没有任何好处。除此之外,你知道的下一件事,他们会要求我做同样的事情!当我们允许客户违反我们的标准时,我们的标准会去哪里?
  • 天哪,我希望。不,是的,我知道我没有帮他们任何忙。也没关系。如果我可以改变它们的用法,我就不会明确指出我的要求不合逻辑。

标签: java xml xslt xpath


【解决方案1】:

如果您希望输出保留“somenamespace”命名空间,但元素上没有命名空间前缀,请在样式表的未命名命名空间(不带前缀)中声明“somenamenamespace”:xmlns='somenamespace '

然后使用 local-name() 创建的元素将具有该命名空间,但不会有命名空间前缀:

<doc xmlns="somenamespace">
    <bar/>
</doc>

您在执行样式表时是否看到关于不明确规则匹配的警告?
“node()”和“*”的模板匹配都会触发一个元素的匹配。

node() 是指定的快捷方式:“*|text()|comment()|processing-instruction()”

您应该做以下两件事之一来解决不明确的匹配:

1.) 更改“@*|node()”的模板匹配以通过显式匹配其他节点类型来排除元素。

<?xml version='1.0' encoding='UTF-8'?> 
<xsl:stylesheet 
    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'  
    xmlns:xs='http://www.w3.org/2001/XMLSchema' 
    xmlns='somenamespace'
    exclude-result-prefixes='xs' 
    version='2.0'> 

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

    <xsl:template match='@*|text()|comment()|processing-instruction()'> 
        <xsl:copy> 
            <xsl:apply-templates select='@*|node()' /> 
        </xsl:copy> 
    </xsl:template> 

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

</xsl:stylesheet>

2.) 将优先级属性添加到“”的模板匹配中,这会提高优先级匹配并确保它被调用以支持“@|node()”。

<?xml version='1.0' encoding='UTF-8'?> 
<xsl:stylesheet 
    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'  
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    xmlns='somenamespace' 
    exclude-result-prefixes='xs' 
    version='2.0'> 

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

    <xsl:template match='@*|node()'> 
        <xsl:copy> 
            <xsl:apply-templates select='@*|node()' /> 
        </xsl:copy> 
    </xsl:template> 

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

</xsl:stylesheet>

【讨论】:

    【解决方案2】:

    不是你想要的模板匹配“sn:*”而不是“*”并且有一个

    <xsl:namespace-alias stylesheet-prefix="sn" result-prefix="#default"/>
    

    另外? (前提是你有 xslns:sn="somenamespace")

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-14
      • 1970-01-01
      • 2012-07-06
      • 2015-04-24
      • 2015-12-14
      • 1970-01-01
      相关资源
      最近更新 更多