首页 文章

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

提问于
浏览
70

嗨,我已经执行了一个转换,如果它是null,则删除一个标记 .

我想检查我的转换是否正常工作,所以不是手动检查,而是编写了一个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文件中存在的所有TEXT DATA,

为了避免这种情况,我不得不写下这段代码::

<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>

为什么以前的代码输出TEXT,为什么我要坚持XSL忽略所有其他文本?是所有XML解析器的行为或仅我自己的行为(我正在使用msxml解析器) .

2 回答

  • 14

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

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

    From the Spec

    存在一个内置模板规则,允许在样式表中的显式模板规则没有成功模式匹配的情况下继续递归处理 . 此模板规则适用于元素节点和根节点 . 以下显示了内置模板规则的等效内容:<xsl:template match =“* | /”>
    的<xsl:应用模板/>
    </ XSL:模板>
    每种模式还有一个内置模板规则,它允许递归处理在样式表中的显式模板规则没有成功模式匹配的情况下以相同模式继续 . 此模板规则适用于元素节点和根节点 . 以下显示模式m的内置模板规则的等效项 . <xsl:template match =“* | /”mode =“m”>
    <xsl:apply-templates mode =“m”/>
    </ XSL:模板>
    还有一个用于文本和属性节点的内置模板规则,用于复制文本:<xsl:template match =“text()| @ *”>
    <xsl:value-of select =“ . ”/>
    </ XSL:模板>
    用于处理指令和注释的内置模板规则是什么都不做 . <xsl:template match =“processing-instruction()| comment()”/>
    命名空间节点的内置模板规则也不做任何事情 . 没有可以匹配命名空间节点的模式;因此,内置模板规则是应用于命名空间节点的唯一模板规则 . 内置模板规则被视为在样式表之前隐式导入,因此导入优先级低于所有其他模板规则 . 因此,作者可以通过包含显式模板规则来覆盖内置模板规则 .

    因此,报告的行为是应用内置模板的结果 - 这三个模板中的第一个和第二个 .

    It is a good XSLT design pattern to override the built-in templates 与您自己一起发出错误消息,以便程序员立即知道他的转换是"leaking":

    For example ,如果有这个XML文档:

    <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>
    

    并且程序员将非常混淆不需要的文本是如何出现的 .

    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

    在XSLT 3.0中,您可以在 xsl:mode 声明上指定回退行为,而不是添加catch-all模板规则 . 例如, <xsl:mode on-no-match="shallow-skip"/> 导致跳过所有不匹配的节点(包括文本节点),而 <xsl:mode on-no-match="fail"/> 将不匹配视为错误, <xsl:mode warning-on-no-match="true"/> 导致警告 .

  • 143

    在XSL中有几个built in template rules,其中一个是这样的:

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

    它输出文字 .

相关问题