检测 XML 文件是否包含特定命名空间

发布于 2024-09-25 20:39:07 字数 610 浏览 2 评论 0原文

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

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

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

我做错了。关于如何改进这个样式表有什么建议吗?


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


事实证明,错误是其他的。我尝试转换的 XML 文件包含处理指令。这个:
我现在遇到的问题是,当我处理包含此 PI 的 XML 文件中,XSLT 开始报告有关未定义的命名空间前缀的错误。那么,如何告诉 XSLT 处理器忽略这条处理指令呢?

Again a simple thing. I have a stylesheet that parses XML and XSL files. Basically, it tries to detect if the XML is a stylesheet with:

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

It does indeed detect stylesheets. It has problems with XML files, though, which generate an "Undefined namespace prefix - 'xsl'" error. (In XmlSpy. Similar errors in the project I'm working on.)

I'm doing something wrong. Any suggestions on how to improve this stylesheet?


Some additional information: This is a stylesheet that's meant to analyse other XML files, no matter what they contain. It should be able to transform itself even, and does so nicely. It has no problem transforming other (normal) stylesheets either. The problem arrives when I try to transform a regular XML file. Yet not all XML files...


As it turns out, the error is something else. The XML files that I tried to transform contain a processing instruction. This one: <?xml-stylesheet href="..\MyStylesheet.xsl" type="text/xsl"?>
The problem I have now is that when I process an XML file that contains this PI, the XSLT starts reporting the error about the undefined namespace prefix. So, how do I tell the XSLT processor to ignore this processing instruction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嘦怹 2024-10-02 20:39:07

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

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

如果它没有在样式表中进一步声明(通常在文档元素上,如下所示: ),或者如果您选择了不同的命名空间前缀(例如将其声明为“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 是文档元素子元素的顶级构造。您可以使用更高效的 XPATH 表达式,而不是使用 // 递归遍历 XML 文档树中的每个节点:

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

Double check how you have declared the xsl namespace and what namespace-prefix you have chosen.

You need to ensure that the xsl namespace prefix is defined in your stylesheet if you want to use it in your XPATH expressions. You will get that error when you try to use a namespace prefix that has not been declared.

If it isn't declared anywhere further up in the stylesheet(typically on the document element like this: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">), or if you have chosen a different namespace prefix (e.g. declared it as "xslt" like this: xmlns:xslt="http://www.w3.org/1999/XSL/Transform"), then when you attempt to reference "xsl" it won't know what you are referring to.

You can declare the xsl namespace prefix on your if statement as a quick test:

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

Any suggestions on how to improve this
stylesheet?

You can simplify your test condition to select the xsl:template elements, rather than evaluating the count() of them. The results of test="//xsl:template" will evaluate as true() if something is selected, and false() if nothing is selected.

In stylesheets xsl:template are top level constructs that are children of the document element. Rather than using // to recurse through every node in the XML document tree, you can use a more efficient XPATH expression:

<xsl:if test="/*/xsl:template" />
几味少女 2024-10-02 20:39:07

假设 XSLT 代码文件始终包含 指令是不正确的。

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

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

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

最后,XSLT 代码文件甚至不能保证包含 指令,因为 XSLT 提供了一个同义词:;

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

/*[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"
           )

It is incorrect to assume that an XSLT code file always contains an <xsl:template> instruction.

There are examples of XSLT stylesheet modules where the file contains just an <xsl:stylesheet> instruction and one or more global-level variables. Such stylesheet module is typically imported/included in another stylesheet module using an <xsl:import> or <xsl:include> instruction.

Also, what defines XSLT is not the prefix of the elements that constitute XSLT instructions. This prefix is not mandated to be "xsl" and some programmers use different prefixes, such as "xslt" or "x".

What really defines XSLT code is the XSLT namespace.

Finally, an XSLT code file isn't guaranteed even to contain an <xsl:stylesheet> directive, because XSLT offers a synonym: <xsl:transform>.

Taking in account all these considerations, a better test would be:

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

Because there exists the possibility of having embedded stylesheets, the test above can be slightly modified to cover these as well:

//*[contains('|stylesheet|transform|', concat('|', local-name(), '|')
          and
            namespace-uri()="http://www.w3.org/1999/XSL/Transform"
           )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文