How to retain the maximum valued mspace, if found

2019-09-03 22:12发布

问题:

Please suggest for retaining maximum valued mspace among successively found mspaces [if text contained elements [mspace] found successively] some times in between there may be other elements like mrow will present, in such cases consecutive text contained spaces only to be consider. See me required out with comments for quick review.

Input XML:

    <article>

<math>
    <mspace>3</mspace>
    <mrow>
        <mspace>3</mspace>
        <mspace>2</mspace>
        <mo>(</mo>
        <mo>+</mo>
        <mo>)</mo>
        <mspace>3</mspace>
   </mrow>
    <mspace>9</mspace>
</math>

<math>
    <mo>[</mo>
    <mrow>
    <mspace>3</mspace>
    <mspace>2</mspace>
    <mspace>3</mspace>
    <mtext>log</mtext>
    <mn>3</mn>
    <mspace>2</mspace>
    </mrow>
    <mspace>2</mspace>
</math>

<math>
    <mspace>3</mspace>
    <mspace>3</mspace>
    <mn>4</mn>
    <mo>-</mo>
    <mi>a</mi>
    <mspace>2</mspace>
</math>


</article>

XSLT:

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

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

<xsl:template match="mspace">
    <xsl:variable name="var1" select="following::text()[normalize-space(.)!=''][1][generate-id(ancestor::math)=generate-id(current()/ancestor::math)]"/>
    <xsl:variable name="var2" select="preceding::text()[normalize-space(.)!=''][1][generate-id(ancestor::math)=generate-id(current()/ancestor::math)]"/>
    <xsl:variable name="var1a" select="following::text()[normalize-space(.)!=''][2][generate-id(ancestor::math)=generate-id(current()/ancestor::math)]"/>
    <xsl:variable name="var2a" select="preceding::text()[normalize-space(.)!=''][2][generate-id(ancestor::math)=generate-id(current()/ancestor::math)]"/>
    <xsl:variable name="vPresent" select="."/>
    <xsl:variable name="vMax" select="max(($var1, $var2, $var1a, $var2a, $vPresent))"/>

    <xsl:choose>
        <xsl:when test="$vPresent lt $var1 or $vPresent lt $var1a">
            <xsl:comment><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:comment>
        </xsl:when>
        <xsl:when test="$vPresent lt $var2 or $vPresent lt $var2a">
            <xsl:comment><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:comment>
        </xsl:when>
        <xsl:when test="$vPresent eq $var2 and $vPresent eq $var1a">
            <xsl:comment><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:comment>
        </xsl:when>

        <xsl:when test="not($vPresent eq $var2) and $vPresent eq $var1">
            <xsl:comment><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:comment>
        </xsl:when>

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

</xsl:template>

</xsl:stylesheet>

Required OutPut:

<?xml version="1.0" encoding="UTF-8"?><article>

<math>
    <!--3-->
    <mrow>
        <mspace>3</mspace>
        <!--2-->
        <mo>(</mo>
        <mo>+</mo>
        <mo>)</mo>
        <!--3-->
   </mrow>
    <mspace>9</mspace>
</math>

<math>
    <mo>[</mo>
    <mrow>
    <!--3-->
    <!--2-->
    <mspace>3</mspace><!--To be required-->
    <mtext>log</mtext>
    <mn>3</mn>
    <mspace>4</mspace><!--To be required-->
    </mrow>
    <!--2-->
</math>

<math>
    <!--3-->
    <mspace>3</mspace><!--To be required-->
    <mn>4</mn>
    <mo>-</mo>
    <mi>a</mi>
    <mspace>2</mspace><!--To be required-->
</math>


</article>

回答1:

Here is my suggestion using 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="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()[. = max(current-group())][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>

It transforms your posted sample into

<article>
   <math><!--3-->
      <mrow>
         <mspace>3</mspace>
         <!--2-->
         <mo>(</mo>
         <mo>+</mo>
         <mo>)</mo>
         <!--3-->
      </mrow>
      <mspace>9</mspace>
   </math>
   <math>
      <mo>[</mo>
      <mrow><!--3--><!--2-->
         <mspace>3</mspace>
         <mtext>log</mtext>
         <mn>3</mn>
         <!--2-->
      </mrow>
      <mspace>2</mspace>
   </math>
   <math><!--3-->
      <mspace>3</mspace>
      <mn>4</mn>
      <mo>-</mo>
      <mi>a</mi>
      <mspace>2</mspace>
   </math>
</article>


标签: xslt