问题描述
我有一个 XSLT 样式表,如下所示:
I have an XSLT stylesheet like the following:
<?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 名称空间有关的任何内容.有没有办法做到这一点?
I want to transform this stylesheet using a second XSLT stylesheet to remove anything that has to do with the XQHeaderFunc and saxon namespaces. Is there a way I can do this?
我现在尝试了以下方法,成功处理了元素,但命名空间声明似乎不想消失.
I have now tried the following, which successfully deals with the elements, but the namespace declaration doesn't seem to want to disappear.
<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>
推荐答案
我会补充
exclude-result-prefixes="foo"
到你的
<xsl:stylesheet>
元素.然后,如果可能,将省略 foo
的命名空间声明,即如果该命名空间中没有要输出的元素或属性.
element. Then the namespace declaration for foo
will be omitted if possible, i.e. if there no elements or attributes in that namespace to output.
仅供参考,这行的原因
<xsl:template match="xsl:stylesheet/@xmlns:foo" />`
抛出错误是因为输入文档中的xmlns:foo
不是属性;这是一个伪属性.您的匹配模式要求匹配的是名为 foo
的属性,该属性位于与命名空间前缀 xmlns
相对应的命名空间中.由于您尚未在样式表中声明命名空间前缀 xmlns
,您会收到错误前缀 xmlns 未定义".
throws an error is because xmlns:foo
in the input document is not an attribute; it's a pseudoattribute. What your match pattern is asking to match is an attribute named foo
that is in a namespace corresponding to a namespace prefix xmlns
. Since you have not declared a namespace prefix xmlns
in your stylesheet, you get the error "prefix xmlns is not defined."
我从您发布的输出(以及我自己的测试)中看到 exclude-result-prefixes
在删除命名空间声明方面没有效果.
I see from your posted output (and my own testing) that exclude-result-prefixes
hasn't been effective in removing the namespace declaration.
1) 首先我会问为什么这很重要.它不会更改输出 XSLT 中任何内容的名称空间.您只是出于审美原因试图将其删除吗?
1) First I would ask why it matters. It doesn't change the namespace of anything in your output XSLT. Are you just trying to remove it for aesthetic reasons?
2) 查看 XSLT 1.0 规范,在我看来 <xsl:copy>
不注意exclude-result-prefixes
:
2) Looking at the XSLT 1.0 spec, it appears to me that <xsl:copy>
pays no attention to exclude-result-prefixes
:
实例化 xsl:copy 元素会创建当前节点的副本.当前节点的命名空间节点被自动复制为嗯...
AFAICT,只有文字结果元素会省略基于 exclude-result-prefixes
的命名空间节点.
AFAICT, only literal result elements will omit namespace nodes based on exclude-result-prefixes
.
在此基础上,我会尝试用 <xsl:element name="{name()}" 替换您的标识模板(对于元素)中的
或其一些变体.然后,您将需要一个用于非元素节点的单独标识模板.<xsl:copy>
>
On that basis, I would try replacing <xsl:copy>
in your identity template (for elements) with <xsl:element name="{name()}">
or some variant thereof. You would then need a separate identity template for non-element nodes.
我用以下两个模板替换了您的身份模板:
I replaced your identity template with the following two templates:
<!-- 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>
这给出了我认为需要的输出,没有多余的 ns 声明:
and that gave what I believe is the desired output, with no extraneous ns declarations:
<?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>
(为了清晰起见,我已经调整了空格.)
(I have adjusted the whitespace for clarity.)
这篇关于使用 XSLT 从 XSLT 样式表中删除命名空间声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!