建议xpath检查相同类型

时间:2015-08-27 14:23:43

标签: xml xpath xslt-2.0

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

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

1 个答案:

答案 0 :(得分:4)

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

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

这是一个应该有帮助的例子......

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>