为什么 XSLT 默认输出所有文本?

发布于 2024-09-12 06:42:36 字数 882 浏览 1 评论 0原文

您好,我执行了一个转换,如果标签为空,则删除该标签。

我想检查我的转换是否正常工作,因此我没有手动检查它,而是编写了另一个 XSLT 代码,该代码仅检查 OUTPUT XML 中是否存在该特定标记,如果它为 null,则第二个 XSLT 应输出文本“找到”。 (我实际上不需要某种 XML 类型的输出,但我只是使用 XSLT 进行搜索。)

当我尝试使用此 XSL 代码 ::

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']">
      FOUND
  </xsl:template>
</xsl:stylesheet>

它输出 XML 文件中存在的所有文本数据时,

为了避免这种情况,我必须编写这段代码::

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']">
      FOUND
  </xsl:template>
  <xsl:template match="text()"/>
</xsl:stylesheet>

为什么前面的代码输出文本,为什么我应该坚持 XSL 忽略所有其他文本?这是所有 XML 解析器的行为还是仅是我自己的行为(我正在使用 msxml 解析器)。

Hi I had performed a transformation which drops a tag if it is null.

I wanted to check whether my transformation is working fine, so instead of checking it manually, I wrote one more XSLT code which just checks the presence of that particular tag in the OUTPUT XML, if it is null, then the second XSLT should output a text "FOUND". (I don't actually need some XML kind of output but I am just using XSLT for searching.)

When I tried with this XSL code ::

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']">
      FOUND
  </xsl:template>
</xsl:stylesheet>

It outputs all the TEXT DATA that is present in the XML file,

to avoid that, I had to write this code::

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']">
      FOUND
  </xsl:template>
  <xsl:template match="text()"/>
</xsl:stylesheet>

why did the former code outputs TEXT, why should I insist XSL to ignore all other text? is that the behavior of all XML parsers or only of my own (I am using msxml parser).

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

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

发布评论

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

评论(2

就是爱搞怪 2024-09-19 06:42:36

为什么前面的代码输出TEXT,
我为什么要坚持 XSL 忽略所有
其他文字?是这样的行为
所有 XML 解析器或仅我自己的

您正在发现规范中指定的最基本的 XSLT 功能之一:XSLT 内置模板

来自规范

有一个内置的模板规则
允许递归处理继续
在没有成功模式的情况下
通过显式模板规则进行匹配
样式表。此模板规则
适用于两个元素节点和
根节点。下图显示了
相当于内置模板
规则:


  >

还有一个内置的模板规则
对于每种模式,允许递归
处理以相同的方式继续
没有成功的模式
通过显式模板进行模式匹配
样式表中的规则。这个模板
规则适用于元素节点和
根节点。下图显示了
相当于内置模板
模式 m 的规则。


  

还有一个内置的模板规则
对于文本和属性节点
通过以下方式复制文本:


  

内置模板规则
处理说明和评论
就是什么也不做。

;

内置模板规则
命名空间节点也是什么都不做。
没有可以匹配的模式
命名空间节点;所以,内置的
模板规则是唯一的模板
应用于命名空间的规则
节点。

内置模板规则是
如同进口一样对待
隐含在样式表之前并且
因此导入优先级低于
所有其他模板规则。因此,
作者可以覆盖内置的
模板规则通过包含显式
模板规则。

因此,报告的行为是应用内置模板的结果——所有三个模板中的第一个和第二个。

用自己的模板覆盖内置模板是一个很好的 XSLT 设计模式,每当调用时都会发出错误消息,以便程序员立即知道他的转换正在“泄漏”:

例如,如果有这样的XML文档:

<a>
  <b>
    <c>Don't want to see this</c>
  </b>
</a>

并且用这种转换处理它

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 
 <xsl:template match="a|b">
   <xsl:copy>
      <xsl:attribute name="name">
        <xsl:value-of select="name()"/>
      </xsl:attribute>
      <xsl:apply-templates/>
   </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

结果是

<a name="a">
   <b name="b">Don't want to see this</b>
</a>

程序员会非常困惑不需要的文本是如何出现的。

但是,只需添加这个包罗万象的模板就可以帮助避免任何此类混乱并立即捕获错误

 <xsl:template match="*">
  <xsl:message terminate="no">
   WARNING: Unmatched element: <xsl:value-of select="name()"/>
  </xsl:message>
  
  <xsl:apply-templates/>
 </xsl:template>

现在,除了令人困惑的输出之外,程序员收到一条警告,立即解释了问题

 WARNING: Unmatched element: c

Michael Kay 对 XSLT 3.0 的后期添加

在 XSLT 3.0 中,您可以指定后备行为,而不是添加包罗万象的模板规则xsl:mode 声明。例如, 会导致跳过所有不匹配的节点(包括文本节点),而 < ;xsl:mode on-no-match="fail"/> 将不匹配视为错误, 会产生警告。

why did the former code outputs TEXT,
why should I insist XSL to ignore all
other text? is that the behavior of
all XML parsers or only of my own

You are discovering one of the most fundamental XSLT features as specified in the Specification: the built-in templates of XSLT.

From the Spec:

There is a built-in template rule to
allow recursive processing to continue
in the absence of a successful pattern
match by an explicit template rule in
the stylesheet. This template rule
applies to both element nodes and the
root node. The following shows the
equivalent of the built-in template
rule:

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>

There is also a built-in template rule
for each mode, which allows recursive
processing to continue in the same
mode in the absence of a successful
pattern match by an explicit template
rule in the stylesheet. This template
rule applies to both element nodes and
the root node. The following shows the
equivalent of the built-in template
rule for mode m.

<xsl:template match="*|/" mode="m">
  <xsl:apply-templates mode="m"/>
</xsl:template>

There is also a built-in template rule
for text and attribute nodes that
copies text through:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

The built-in template rule for
processing instructions and comments
is to do nothing.

<xsl:template match="processing-instruction()|comment()"/>

The built-in template rule for
namespace nodes is also to do nothing.
There is no pattern that can match a
namespace node; so, the built-in
template rule is the only template
rule that is applied for namespace
nodes.

The built-in template rules are
treated as if they were imported
implicitly before the stylesheet and
so have lower import precedence than
all other template rules. Thus, the
author can override a built-in
template rule by including an explicit
template rule.

So, the reported behavior is the result of the application of the built-in templates -- the 1st and 2nd of all three of them.

It is a good XSLT design pattern to override the built-in templates with your own that will issue an error message whenever called so that the programmer immediately knows his transformation is "leaking":

For example, if there is this XML document:

<a>
  <b>
    <c>Don't want to see this</c>
  </b>
</a>

and it is processed with this transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 
 <xsl:template match="a|b">
   <xsl:copy>
      <xsl:attribute name="name">
        <xsl:value-of select="name()"/>
      </xsl:attribute>
      <xsl:apply-templates/>
   </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

the result is:

<a name="a">
   <b name="b">Don't want to see this</b>
</a>

and the programmer will be greatly confused how the unwanted text appeared.

However, just adding this catch-all template helps avoid any such confusion and catch errors immediately:

 <xsl:template match="*">
  <xsl:message terminate="no">
   WARNING: Unmatched element: <xsl:value-of select="name()"/>
  </xsl:message>
  
  <xsl:apply-templates/>
 </xsl:template>

Now, besides the confusing output the programmer gets a warning that explains the problem immediately:

 WARNING: Unmatched element: c

Later Addition by Michael Kay for XSLT 3.0

In XSLT 3.0, rather than adding a catch-all template rule, you can specify the fallback behaviour on an xsl:mode declaration. For example, <xsl:mode on-no-match="shallow-skip"/> causes all nodes that are not matched (including text nodes) to be skipped, while <xsl:mode on-no-match="fail"/> treats a no-match as an error, and <xsl:mode warning-on-no-match="true"/> results in a warning.

国际总奸 2024-09-19 06:42:36

XSL 中有多个内置模板规则,其中之一是:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

输出文本。

There are several built in template rules in XSL, one of which is this:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

It outputs text.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文