1

又是一件简单的事情。我有一个解析 XML 和 XSL 文件的样式表。基本上,它会尝试检测 XML 是否是样式表:

<xsl:if test="count(//xsl:template)!=0">

它确实检测到样式表。但是,XML 文件存在问题,会生成“未定义的命名空间前缀 - 'xsl' ”错误。(在 XmlSpy 中。我正在处理的项目中有类似的错误。)

我做错了什么。有关如何改进此样式表的任何建议?


一些附加信息:这是一个用于分析其他 XML 文件的样式表,无论它们包含什么。它甚至应该能够自我改造,而且做得很好。转换其他(正常)样式表也没有问题。当我尝试转换常规 XML 文件时,问题就来了。然而,并非所有 XML 文件...


事实证明,错误是另一回事。我尝试转换的 XML 文件包含处理指令。这个:<?xml-stylesheet href="..\MyStylesheet.xsl" type="text/xsl"?>
我现在遇到的问题是,当我处理包含此 PI 的 XML 文件时,XSLT 开始报告有关未定义名称空间前缀的错误。那么,我如何告诉 XSLT 处理器忽略这个处理指令呢?

4

2 回答 2

1

仔细检查您如何声明xsl命名空间以及您选择的命名空间前缀。

xsl如果要在 XPATH 表达式中使用名称空间前缀,则需要确保在样式表中定义了名称空间前缀。 当您尝试使用尚未声明的命名空间前缀时,您将收到该错误。

如果它没有在样式表中的任何位置进一步声明(通常在文档元素上像这样:)<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">,或者如果您选择了不同的命名空间前缀(例如,像这样将其声明为“ xsltxmlns:xslt="http://www.w3.org/1999/XSL/Transform" ”:) ,那么当您尝试参考“ xsl ”它不会知道你指的是什么。

您可以xsl在语句中声明命名空间前缀if作为快速测试:

<xsl:if test="count(//xsl:template)!=0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

有关如何改进此样式表的任何建议?

您可以简化测试条件以选择xsl:template元素,而不是评估其中的元素count()。的结果test="//xsl:template"将评估为true()是否选择了某些内容,false()如果没有选择任何内容。

在样式表xsl:template中是顶层结构,它们是文档元素的子元素。//您可以使用更高效的 XPATH 表达式,而不是使用递归遍历 XML 文档树中的每个节点:

<xsl:if test="/*/xsl:template" />
于 2010-10-01T11:54:25.007 回答
1

假设 XSLT 代码文件总是包含<xsl:template>指令是不正确的。

有一些 XSLT 样式表模块的示例,其中文件仅包含一条<xsl:stylesheet>指令和一个或多个全局级变量。这种样式表模块通常使用<xsl:import>or<xsl:include>指令导入/包含在另一个样式表模块中。

此外,定义 XSLT 的不是构成 XSLT 指令的元素的前缀。这个前缀不是强制性的"xsl",一些程序员使用不同的前缀,例如"xslt"or "x"

真正定义 XSLT 代码的是 XSLT 名称空间

最后,甚至不能保证 XSLT 代码文件包含<xsl:stylesheet>指令,因为 XSLT 提供了同义词:<xsl:transform>.

考虑到所有这些因素,更好的测试是:

/*[contains('|stylesheet|transform|', concat('|', local-name(), '|')
          and
            namespace-uri()="http://www.w3.org/1999/XSL/Transform"
           )

因为存在嵌入样式表的可能性,所以上面的测试可以稍微修改以涵盖这些:

//*[contains('|stylesheet|transform|', concat('|', local-name(), '|')
          and
            namespace-uri()="http://www.w3.org/1999/XSL/Transform"
           )
于 2010-10-01T13:04:30.090 回答