建议 xpath 检查相同类型的嵌套元素中的第一个 'text' 节点

Suggest the xpath to check the first 'text' node within nested elements of same type

请建议要检查的 xpath,元素 'mo' 是否在 'mfrac' 的第一个子元素中以 'text node' 开头。目前的 XSLT 代码对于所有 'mfrac' 都成功 运行,其中那些不应该嵌套在一个 'mfrac' 中(数学 1 和 2 是 运行 成功,但数学 3 不是) .如果 'mfrac' 被另外一个 'mfrac' 嵌套,则会出现一些错误消息。需要的输出是 'mo' 应该得到属性 'form=prefix',如果 'mo' 没有在 'mfrac/child::*' 之前的文本节点('mo' 作为第一个文本节点)。请建议如何避免错误消息。忽略结果文本中的评论。

XML:

<article>
<body>
    <p>
        <math id="eq1"><mi>i</mi>
            <mfrac>
                <mrow><mo>+</mo></mrow>
                <mrow><mi>t</mi></mrow>
            </mfrac>
        </math>
        <math id="eq2">
            <mfrac>
                <mrow><mi>i</mi><mo>+</mo></mrow>
                <mrow><mi>t</mi></mrow>
            </mfrac>
        </math>

        <math id="eq3"><mi>i</mi><mfrac><mrow><mfrac><mo>+</mo><mi>n</mi></mfrac></mrow><mrow><mi>t</mi></mrow></mfrac></math>
    </p>
</body>
</article>

XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

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

<xsl:template match="mo">
    <xsl:choose>
        <xsl:when test="string-length(preceding::text()[1]
                  [normalize-space(.)!='']
                  [generate-id(ancestor-or-self::*[count(preceding-sibling::*)=0]/parent::*[name()='mfrac'])=generate-id(current()/ancestor-or-self::*[count(preceding-sibling::*)=0]/parent::*[name()='mfrac'])]) eq 0">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="form" select="'prefix'"/>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
        </xsl:otherwise>
    </xsl:choose>

</xsl:template>

要求输出:

<article>
<body>
    <p>
        <mmlmath id="eq1"><mi>i</mi>
            <mfrac>
                <mrow><mo form="prefix">+</mo></mrow><!--Here prefix attribute required because MO found as first text node within MFRAC's first child-->
                <mrow><mi>t</mi></mrow>
            </mfrac>
        </mmlmath>
        <mmlmath id="eq2">
            <mfrac>
                <mrow><mi>i</mi><mo>+</mo></mrow><!--Here attribute not required because 'MO' is not a first text node-->
                <mrow><mi>t</mi></mrow>
            </mfrac>
        </mmlmath>

        <mmlmath id="eq3"><mi>i</mi><mfrac><mrow><mfrac><!--Nested MFRAC--><mo form="prefix">+</mo><!--Attribute required here--><mi>n</mi></mfrac></mrow><mrow><mi>t</mi></mrow></mfrac></mmlmath>
    </p>
</body>
</article>

错误信息:

XPTY0004: A sequence of more than one item is not allowed as the first argument of  generate-id() (<mfrac/>, <mfrac/>)

您应该能够测试当前 mo 是否是包含 text() 节点的第一个祖先 mfrac 的第一个后代。

希望这是有道理的。 :-)

这里有一个示例,应该对您有所帮助...

XML 输入

<article>
    <body>
        <p>
            <math id="eq1">
                <mi>i</mi>
                <mfrac>
                    <mrow>
                        <mo>+</mo>
                    </mrow>
                    <mrow>
                        <mi>t</mi>
                    </mrow>
                </mfrac>
            </math>
            <math id="eq2">
                <mfrac>
                    <mrow>
                        <mi>i</mi>
                        <mo>+</mo>
                    </mrow>
                    <mrow>
                        <mi>t</mi>
                    </mrow>
                </mfrac>
            </math>
            <math id="eq3">
                <mi>i</mi>
                <mfrac>
                    <mrow>
                        <mfrac>
                            <mo>+</mo>
                            <mi>n</mi>
                        </mfrac>
                    </mrow>
                    <mrow>
                        <mi>t</mi>
                    </mrow>
                </mfrac>
            </math>
        </p>
    </body>
</article>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="mo[. is (ancestor::mfrac[1]//*[text()])[1]]">
        <xsl:copy>
            <xsl:attribute name="form" select="'prefix'"/>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

XML输出

<article>
   <body>
      <p>
         <math id="eq1">
            <mi>i</mi>
            <mfrac>
               <mrow>
                  <mo form="prefix">+</mo>
               </mrow>
               <mrow>
                  <mi>t</mi>
               </mrow>
            </mfrac>
         </math>
         <math id="eq2">
            <mfrac>
               <mrow>
                  <mi>i</mi>
                  <mo>+</mo>
               </mrow>
               <mrow>
                  <mi>t</mi>
               </mrow>
            </mfrac>
         </math>
         <math id="eq3">
            <mi>i</mi>
            <mfrac>
               <mrow>
                  <mfrac>
                     <mo form="prefix">+</mo>
                     <mi>n</mi>
                  </mfrac>
               </mrow>
               <mrow>
                  <mi>t</mi>
               </mrow>
            </mfrac>
         </math>
      </p>
   </body>
</article>