2010-10-01 71 views
1

再次是一件简单的事情。我有一个分析XML和XSL文件的样式表。基本上,它试图检测XML是否是样式表:检测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处理器忽略这个处理指令呢?

+0

亚历克斯:这是一个奇怪的错误报告。如果查询没有XSLT名称空间的XML树,它应该导致一个空的节点集,而不是一个错误。 – 2010-10-01 12:11:07

+0

好问题(+1)。查看我的答案以获得详细的分析和简短而全面的解决方案。 – 2010-10-01 13:05:30

回答

1

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

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

如果没有在样式表(通常这样的文档元素:<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">)宣布任何地方进一步上涨,或者如果你选择了一个不同的命名空间的前缀(例如,宣称其为“XSLT”是这样的: xmlns:xslt="http://www.w3.org/1999/XSL/Transform"),那么当您尝试引用“xsl”时,它将不知道您所指的是什么。

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

<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是顶层构造,它们是文档元素的子元素。而不是使用//通过在XML文档树的每个节点递归,您可以使用更高效的XPath表达式:

<xsl:if test="/*/xsl:template" /> 
1

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

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

此外,定义XSLT的不是构成XSLT指令的元素的前缀。此前缀不强制为"xsl",某些程序员使用不同的前缀,例如"xslt""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" 
      ) 

由于存在具有embedded stylesheets的可能性,上述试验可以稍加修改,以覆盖这些以及:

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

我知道这是不正确的,但如果没有,我不想显示任何信息。使用样式表时,我只收集@match,@mode和@name属性以显示在报表中。该系统只是试图检测XML文件是否是我定义的任何已知类型。如果没有,这不是很有趣。不过,非常好的一点! – 2010-10-01 13:42:11

0

为什么您需要检查“/ xsl:template | xsl:transform”之外的任何内容?那些必须处于顶级水平,并且只有才能处于顶级水平。

+0

我不需要。但是XML文件可能是或者可能不是XSLT文件。我正在处理的项目从特殊资源接收XML数据,需要检测它是什么并提供有关内容的信息。使用XSLT文件,我需要列出模板。对于其他XML文件,我需要从40个不同的文件中检查它的格式并显示它的内容。这就是所要做的。 – 2010-10-17 12:56:27