如果连续与其他mspaces一起找到,如何保留最大值mspace(具有字母数字内容)

时间:2014-11-17 10:48:20

标签: xslt

请建议在连续找到的mspace中保留最大值mspace(具有字母数字内容)[如果连续找到文本包含元素[mspace]]可能还有其他元素,如mrow会出现,在这种情况下,连续文本只包含要考虑的空格。请参阅上一篇文章,了解数值Space with Numeric values

输入XML:

<article>

<math>
    <mspace>aaaaa3pts</mspace>
    <mrow>
        <mspace>aaaaa3pts</mspace>
        <mspace>aaaaa2pts</mspace>
        <mo>(</mo>
        <mo>+</mo>
        <mo>)</mo>
        <mspace>aaaaa3pts</mspace>
   </mrow>
    <mspace>aaaaa9pts</mspace>
</math>

<math>
    <mo>[</mo>
    <mrow>
    <mspace>aaaaa3pts</mspace>
    <mspace>aaaaa2pts</mspace>
    <mspace>aaaaa3pts</mspace>
    <mtext>log</mtext>
    <mn>3</mn>
    <mspace>aaaaa4pts</mspace>
    </mrow>
    <mspace>aaaaa2pts</mspace>
</math>

<math>
    <mspace>aaaaa3pts</mspace>
    <mspace>aaaaa3pts</mspace>
    <mn>4</mn>
    <mo>-</mo>
    <mi>a</mi>
    <mspace>aaaaa2pts</mspace>
</math>


</article>

XSLT:

<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="math[descendant::mspace]">
   <xsl:copy>
     <xsl:variable name="max-elements" as="element(mspace)*">
       <xsl:for-each-group select="descendant::*[not(*)]" group-adjacent="boolean(self::mspace)">
         <xsl:if test="current-grouping-key()">
           <xsl:sequence select="current-group()[substring-before(substring-after(., 'space'), 'pts') = max(current-group(substring-before(substring-after(., 'space'), 'pts'))][last()]"/>
         </xsl:if>
       </xsl:for-each-group>
     </xsl:variable>
     <xsl:apply-templates select="@*"/>
     <xsl:apply-templates select="node()">
       <xsl:with-param name="max-elements" select="$max-elements" tunnel="yes"/>
     </xsl:apply-templates>
   </xsl:copy>
 </xsl:template>

 <xsl:template match="mspace">
   <xsl:param name="max-elements" tunnel="yes"/>
   <xsl:choose>
     <xsl:when test=". intersect $max-elements">
       <xsl:next-match/>
     </xsl:when>
     <xsl:otherwise>
       <xsl:comment select="."/>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>

</xsl:stylesheet>

必需的OutPut:

    <?xml version="1.0" encoding="UTF-8"?>
<article>
    <math>
     <!--3-->
    <mrow>
         <mspace>space3pts</mspace>
         <!--2-->
          <mo>(</mo>
         <mo>+</mo>
         <mo>)</mo>
         <!--3-->
     </mrow>
      <mspace>space9pts</mspace>
   </math>
   <math>
      <mo>[</mo>
      <mrow>
    <!--3-->
    <!--2-->
     <mspace>space3pts</mspace>
         <mtext>log</mtext>
         <mn>3</mn>
         <mspace>space4pts</mspace>
      </mrow>
      <!--2-->
    </math>
    <math>
    <!--3-->
      <mspace>space3pts</mspace>
      <mn>4</mn>
      <mo>-</mo>
      <mi>a</mi>
      <mspace>space2pts</mspace>
   </math>
</article>

1 个答案:

答案 0 :(得分:1)

如果单位始终为pts并且您只想比较其中包含的数字值,那么您可以删除所有字母以提取数字:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="xs mf">

 <xsl:output indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:function name="mf:extract-number" as="xs:decimal">
   <xsl:param name="input" as="xs:string"/>
   <xsl:sequence select="xs:decimal(replace($input, '(^\p{L}+)|(\p{L}+$)', ''))"/>
 </xsl:function>

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

 <xsl:template match="math[descendant::mspace]">
   <xsl:copy>
     <xsl:variable name="max-elements" as="element(mspace)*">
       <xsl:for-each-group select="descendant::*[not(*)]" group-adjacent="boolean(self::mspace)">
         <xsl:if test="current-grouping-key()">
           <xsl:sequence select="current-group()[mf:extract-number(.) = max(current-group()/mf:extract-number(.))][last()]"/>
         </xsl:if>
       </xsl:for-each-group>
     </xsl:variable>
     <xsl:apply-templates select="@*"/>
     <xsl:apply-templates select="node()">
       <xsl:with-param name="max-elements" select="$max-elements" tunnel="yes"/>
     </xsl:apply-templates>
   </xsl:copy>
 </xsl:template>

 <xsl:template match="mspace">
   <xsl:param name="max-elements" tunnel="yes"/>
   <xsl:choose>
     <xsl:when test=". intersect $max-elements">
       <xsl:copy>
         <xsl:value-of select="concat('space', mf:extract-number(.), 'pts')"/>
       </xsl:copy>
     </xsl:when>
     <xsl:otherwise>
       <xsl:comment select="mf:extract-number(.)"/>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>

</xsl:stylesheet>