【问题标题】:template with specified mode does not match problem指定模式的模板不匹配问题
【发布时间】:2020-02-18 08:21:07
【问题描述】:

我需要计算一些值并将它们存储在一个变量中。我将一个文档节点传递给xsl:apply-templates 并指定模式:

<xsl:variable as="xs:string*" name="checkAccidentalsVisibility">        
    <xsl:apply-templates  mode="checkAccidentalsVisibility" select="$extractMainVersion"/>  
</xsl:variable>

但是这个模式的模板不匹配:

<xsl:template match="body//@accid[not(parent::accid/@func[. = 'caution'] or ancestor::note[@grace])]" mode="checkAccidentalsVisibility" >...

身份转换模板是这样指定的,bcs我不需要复制xml树。

<xsl:template match="node() | @*" mode="extractMainVersion changeAccid">
    <xsl:copy>
        <xsl:apply-templates mode="#current" select="node() | @*"/>
    </xsl:copy>
</xsl:template>

$checkAccidentalsVisibility 的值是文本节点。例如,应用于这个 XML 我得到 一个例子

<?xml version="1.0" encoding="UTF-8"?>
    <mei meiversion="3.0.0" xml:id="dme92517025-f4c2-4231-a1c3-b70f02802d61" xmlns="http://www.music-encoding.org/ns/mei">
        <meiHead meiversion="3.0.0">
            <fileDesc>
                <titleStmt>
                    <title label="NMA digital" type="unit">an example</title>
                </titleStmt>
                <pubStmt/>
            </fileDesc>
        </meiHead>
        <music meiversion="3.0.0">
            <body>
                <mdiv n="2a" xml:id="mdiv_">
                    <score xml:id="score_">                     
                        <section label="menuetto_A" xml:id="section_A_m1-5">
                            <measure n="1" xml:id="m1_k_">
                                <staff n="1" xml:id="staff_108">
                                    <layer n="1" xml:id="layer_114">
                                        <note accid.ges="f" dur="2" oct="4" pname="e" tstamp="1" xml:id="note_120"/>
                                        <choice xml:id="choice_132">
                                            <sic xml:id="corr_132">
                                                <note dur="4" oct="4" pname="e" tstamp="3" xml:id="note_132">
                                                    <accid accid="f"  xml:id="accid_138"/>
                                                </note>
                                            </sic>
                                            <orig xml:id="orig_132">
                                                <note dur="4" oct="4" pname="e" tstamp="3" xml:id="note_132b">
                                                    <accid accid="f"  xml:id="accid_138b"/>
                                                </note>
                                            </orig>
                                        </choice>
                                    </layer>
                                </staff>
                            </measure>
                        </section>
                    </score>
                </mdiv>
            </body>
        </music>
    </mei>

我期待一系列 @xml:id-values 我从我的计算中得出的。

【问题讨论】:

  • XML 元素位于命名空间xmlns="http://www.music-encoding.org/ns/mei" 中,在使用xpath-default-namespace="http://www.music-encoding.org/ns/mei" 的XSLT 中是否考虑了该命名空间?
  • 是的,这是默认命名空间。我刚刚意识到我只能匹配元素,但不能匹配属性。例如,match="body" 可以正常工作,但 match="@accid" 甚至 match="@*" 什么都不选择。
  • 我建议您将代码示例减少到最少但完整的示例,以便其他人重现问题。不清楚输入是什么,变量$extractMainVersion绑定在哪里以及如何绑定,不同模式是如何使用的。
  • 在变量声明中给出as="xs:string*",声称“$checkAccidentalsVisibility 的值是文本节点”似乎很奇怪,字符串序列不是文本节点。

标签: xml xslt


【解决方案1】:

据我从提供的代码片段中可以看出,您还没有为模式checkAccidentalsVisibility 定义任何“后备”模板,因此当您在此模式下将模板应用到文档节点时,内置模板规则开始生效,元素的默认规则使用应用模板来处理元素的子元素,而不是其属性。所以属性不会被处理。

【讨论】:

    【解决方案2】:

    正如Michael Kay 指出的那样,默认属性模板缺少覆盖,后者类似于:

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

    所以你应该添加类似的东西:

    <xsl:template match="node()|@*" mode="checkAccidentalsVisibility">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    

    【讨论】:

      【解决方案3】:

      当显式地将属性传递给@select 时,它们是匹配的。所以,:

      <xsl:apply-templates  mode="checkAccidentalsVisibility" select="$extractMainVersion//@accid"/>
      

      在这里匹配:

      <xsl:template match="body//@accid[not(parent::accid/@func[. = 'caution'] or ancestor::note[@grace])]" mode="checkAccidentalsVisibility">
      

      @Martin Honnen:$extractMainversion 包含一个文档节点,其值为 &lt;#documentfragment&gt;,与上面的 XML sn-p 几乎相同。 $checkAccidentalsVisibility 之前包含一个从//title/text() 派生的字符串,可能我描述得不好。

      虽然我解决了这个问题,但我很感兴趣,为什么你不能像通常在没有模式的情况下那样匹配@attributes?

      【讨论】:

      • “为什么你不能像没有模式的情况下那样匹配@attributes”:你有没有证据表明它正在使用阻止你的示例按预期工作的模式?您既没有展示一个没有模式的完整示例,也没有展示一个完整的有模式的示例,并对比了您获得的不同结果。如果仅在树结构中选择更高的节点时处理未到达属性,则可能存在此类节点的模板,这些节点不选择属性进行进一步处理。
      【解决方案4】:

      整个 xslt 相当大且模块化。我不知道如何在这里发布所有内容......例如这是主要的样式表:

      <?xml version="1.0" encoding="UTF-8"?>
      <xsl:stylesheet exclude-result-prefixes="xs xd mei dme map" version="3.0" xmlns:dme="http://www.mozarteum.at/ns/dme" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:mei="http://www.music-encoding.org/ns/mei" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.music-encoding.org/ns/mei">
      
      
          <xsl:include href="modules/basic.xsl"/>
          <xsl:include href="modules/extractMainVersion.xsl"/>
          <xsl:include href="modules/check_contextNote.xsl"/>
          <xsl:include href="modules/changeAccid.xsl"/>
      
      
          <xsl:variable as="xs:string*" name="checkAccidentalsVisibility">
              <xsl:variable name="extractMainVersion">
                  <xsl:apply-templates mode="extractMainVersion" select="."/>
              </xsl:variable>
              <xsl:apply-templates  mode="checkAccidentalsVisibility" select="$extractMainVersion//@accid"/>
          </xsl:variable>
      
          <xd:doc>
              <xd:desc/>
          </xd:doc>
          <xsl:template match="/">
              <xsl:apply-templates mode="changeAccid" select="."/>
          </xsl:template>
      
      </xsl:stylesheet>
      

      模板

      <xsl:template match="body//@accid[not(parent::accid/@func[. = 'caution'] or ancestor::note[@grace])]" mode="checkAccidentalsVisibility" >...
      

      放置在check_contextNote.xsl。这是唯一具有 checkAccidentalsVisibility 模式的模板,但它稍后会调用许多其他模板和函数。

      原来我没有$checkAccidentalsVisibility,也不需要各种模式,模板匹配的很好。后来,我需要更改程序逻辑并分离以下内容:

      1. 根据计算值更改原始文档节点()
      2. 值应该从修改后的 document-node() 计算出来(这就是 $extractMainVersion 包含的内容)

      所以我添加了三种模式。其中两个我添加到身份转换模板中(最初,它被设置为#all)。这是basic.xsl

         <xsl:stylesheet exclude-result-prefixes="xs xd mei dme map" version="3.0" xmlns:dme="http://www.mozarteum.at/ns/dme" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:mei="http://www.music-encoding.org/ns/mei" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.music-encoding.org/ns/mei">
      
              <xsl:output encoding="UTF-8" indent="yes" method="xml"/>
              <xsl:strip-space elements="*"/>
      
              <xsl:template match="node() | @*" mode="extractMainVersion changeAccid">
                  <xsl:copy>
                      <xsl:apply-templates mode="#current" select="node() | @*"/>
                  </xsl:copy>
              </xsl:template>
      
          </xsl:stylesheet>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-03
        • 1970-01-01
        • 2011-06-17
        • 2020-07-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多