0

我想从<mo></mo>直到<mo>)转变</mo><mfenced>...... </mfenced>示例输入如下:

示例 XML:

<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://www.w3.org/1998/Math/MathML">
  <p>
    <math>
      <mi>sin</mi>
      <mo>(</mo>
      <mi>x</mi>
      <mi>y</mi>
      <mo>)</mo>
      <mo>=</mo>
      <mi>sin</mi>
      <mi>x</mi>
      <mi>sin</mi>
      <mi>y</mi>
    </math>
  </p>
</chapter>

XSLT 2.0 试过:

<?xml version='1.0'?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:m="http://www.w3.org/1998/Math/MathML"
    xmlns="http://www.w3.org/1998/Math/MathML"
    exclude-result-prefixes="m">

  <xsl:output method="xml"/>

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

  <xsl:template match="m:mo">
    <xsl:if test="(.)='('">
      <mfenced><xsl:apply-templates select="following-sibling::*[(.)=')']" mode="copy"/>
      </mfenced>
    </xsl:if>
    <xsl:if test="(.)=')'"></xsl:if>
  </xsl:template>

  <xsl:template match="m:mo" mode="copy"/>

</xsl:stylesheet>

需要输出:

<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://www.w3.org/1998/Math/MathML">
  <p>
    <math>
      <mi>sin</mi>
      <mfenced>
        <mi>x</mi>
        <mi>y</mi>
      </mfenced>
      <mo>=</mo>
      <mi>sin</mi>
      <mi>x</mi>
      <mi>sin</mi>
      <mi>y</mi>
    </math>
  </p>
</chapter>
4

3 回答 3

1

这是我用来将 mo 中的括号转换为 mfenced 的 xslt。

它使用查找匹配括号的算法。

<?xml version='1.0'?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:m="http://www.w3.org/1998/Math/MathML"
    xmlns="http://www.w3.org/1998/Math/MathML"
    exclude-result-prefixes="m">

  <xsl:output method="xml"/>

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

<xsl:template match="m:mo[(.)='(']">
<xsl:variable name="brcount">
<xsl:value-of select="count(following-sibling::m:mo[(.)='(' or (.)=')'])"/>
</xsl:variable>
 <xsl:call-template name="for.oploop">
 <xsl:with-param name="i"><xsl:value-of select="'0'"/></xsl:with-param>
 <xsl:with-param name="j"><xsl:value-of select="'1'"/></xsl:with-param> 
 <xsl:with-param name="count"><xsl:value-of select="$brcount"/></xsl:with-param>
 <xsl:with-param name="stringop"><xsl:value-of select="'('"/></xsl:with-param> 
 <xsl:with-param name="stringcl"><xsl:value-of select="')'"/></xsl:with-param> 
 </xsl:call-template>
</xsl:template>

<xsl:template match="m:mo[(.)=')']">
<xsl:variable name="brcount">
<xsl:value-of select="count(preceding-sibling::m:mo[(.)='(' or (.)=')'])"/>
</xsl:variable>
 <xsl:call-template name="for.clloop">
 <xsl:with-param name="i"><xsl:value-of select="'0'"/></xsl:with-param>
 <xsl:with-param name="j"><xsl:value-of select="'1'"/></xsl:with-param> 
 <xsl:with-param name="count"><xsl:value-of select="$brcount"/></xsl:with-param>
 <xsl:with-param name="stringop"><xsl:value-of select="'('"/></xsl:with-param> 
 <xsl:with-param name="stringcl"><xsl:value-of select="')'"/></xsl:with-param>  
 </xsl:call-template>
</xsl:template>

<xsl:template match="m:mo[(.)='[']">
<xsl:variable name="brcount">
<xsl:value-of select="count(following-sibling::m:mo[(.)='[' or (.)=']'])"/>
</xsl:variable>
 <xsl:call-template name="for.oploop">
 <xsl:with-param name="i"><xsl:value-of select="'0'"/></xsl:with-param>
 <xsl:with-param name="j"><xsl:value-of select="'1'"/></xsl:with-param> 
 <xsl:with-param name="count"><xsl:value-of select="$brcount"/></xsl:with-param>
 <xsl:with-param name="stringop"><xsl:value-of select="'['"/></xsl:with-param> 
 <xsl:with-param name="stringcl"><xsl:value-of select="']'"/></xsl:with-param> 
 </xsl:call-template>
</xsl:template>

<xsl:template match="m:mo[(.)=']']">
<xsl:variable name="brcount">
<xsl:value-of select="count(preceding-sibling::m:mo[(.)='[' or (.)=']'])"/>
</xsl:variable>
 <xsl:call-template name="for.clloop">
 <xsl:with-param name="i"><xsl:value-of select="'0'"/></xsl:with-param>
 <xsl:with-param name="j"><xsl:value-of select="'1'"/></xsl:with-param> 
 <xsl:with-param name="count"><xsl:value-of select="$brcount"/></xsl:with-param>
 <xsl:with-param name="stringop"><xsl:value-of select="'['"/></xsl:with-param> 
 <xsl:with-param name="stringcl"><xsl:value-of select="']'"/></xsl:with-param>  
 </xsl:call-template>
</xsl:template>


<xsl:template name="for.oploop">
        <xsl:param name="i"      />
        <xsl:param name="j"      />        
        <xsl:param name="count"  />
        <xsl:param name="stringop"  />        
        <xsl:param name="stringcl"  />        
        <xsl:if test="$i = $count">        
        <xsl:if test="$j &gt; '0'">
            <xsl:text disable-output-escaping="yes">&lt;mfenced separators="" open="</xsl:text>
          <xsl:value-of select="$stringop"/>
          <xsl:text disable-output-escaping="yes">" close=""&gt;&lt;/mfenced&gt;</xsl:text>
        </xsl:if>          
        <xsl:if test="$j = '0'">
            <xsl:text disable-output-escaping="yes">&lt;mfenced separators="" open="</xsl:text>
          <xsl:value-of select="$stringop"/>
          <xsl:text disable-output-escaping="yes">" close="</xsl:text>
          <xsl:value-of select="$stringcl"/>
          <xsl:text disable-output-escaping="yes">"&gt;</xsl:text>        
        </xsl:if>  
        </xsl:if>
        <xsl:if test="$i &lt; $count">
                <xsl:choose>
                 <xsl:when test="$j = '0'">
            <xsl:text disable-output-escaping="yes">&lt;mfenced separators="" open="</xsl:text>
          <xsl:value-of select="$stringop"/>
          <xsl:text disable-output-escaping="yes">" close="</xsl:text>
          <xsl:value-of select="$stringcl"/>
          <xsl:text disable-output-escaping="yes">"&gt;</xsl:text>        
                 </xsl:when>
                 <xsl:otherwise>
                  <xsl:choose>
                   <xsl:when test="following-sibling::m:mo[(.)=$stringop or (.)=$stringcl][$i + 1] = $stringop">
                                    <xsl:call-template name="for.oploop">
                        <xsl:with-param name="i">
                                <xsl:value-of select="$i + 1"/>
                        </xsl:with-param>
                        <xsl:with-param name="j">
                                <xsl:value-of select="$j + 1"/>
                        </xsl:with-param>                        
                        <xsl:with-param name="count">
                                <xsl:value-of select="$count"/>
                        </xsl:with-param>                                                
                        <xsl:with-param name="stringop"><xsl:value-of select="$stringop"/></xsl:with-param> 
                        <xsl:with-param name="stringcl"><xsl:value-of select="$stringcl"/></xsl:with-param>                                                 
                    </xsl:call-template>                
                   </xsl:when>
                   <xsl:when test="following-sibling::m:mo[(.)=$stringop or (.)=$stringcl][$i + 1] = $stringcl">
                                    <xsl:call-template name="for.oploop">
                        <xsl:with-param name="i">
                                <xsl:value-of select="$i + 1"/>
                        </xsl:with-param>
                        <xsl:with-param name="j">
                                <xsl:value-of select="$j - 1"/>
                        </xsl:with-param>                        
                        <xsl:with-param name="count">
                                <xsl:value-of select="$count"/>
                        </xsl:with-param>                        
                        <xsl:with-param name="stringop"><xsl:value-of select="$stringop"/></xsl:with-param> 
                        <xsl:with-param name="stringcl"><xsl:value-of select="$stringcl"/></xsl:with-param>                                                 
                    </xsl:call-template>                
                  </xsl:when>                
                  <xsl:otherwise/>
                  </xsl:choose>
                </xsl:otherwise>                
                </xsl:choose>
        </xsl:if>
</xsl:template>

<xsl:template name="for.clloop">
        <xsl:param name="i"      />
        <xsl:param name="j"      />        
        <xsl:param name="count"  />
        <xsl:param name="stringop"  />        
        <xsl:param name="stringcl"  />                
        <xsl:if test="$i = $count">
        <xsl:if test="$j &gt; '0'">
            <xsl:text disable-output-escaping="yes">&lt;mfenced separators="" open="" close="</xsl:text>
           <xsl:value-of select="$stringcl"/>
          <xsl:text disable-output-escaping="yes">"&gt;&lt;/mfenced&gt;</xsl:text>
        </xsl:if>          
        <xsl:if test="$j = '0'">
            <xsl:text disable-output-escaping="yes">&lt;/mfenced&gt;</xsl:text>
        </xsl:if>  
        </xsl:if>
        <xsl:if test="$i &lt; $count">
                <xsl:choose>
                 <xsl:when test="$j = '0'">
                                    <xsl:text disable-output-escaping="yes">&lt;/mfenced&gt;</xsl:text>
                 </xsl:when>
                 <xsl:otherwise>
                  <xsl:choose>
                   <xsl:when test="preceding-sibling::m:mo[(.)=$stringop or (.)=$stringcl][$i + 1] = $stringop">
                                    <xsl:call-template name="for.clloop">
                        <xsl:with-param name="i">
                                <xsl:value-of select="$i + 1"/>
                        </xsl:with-param>
                        <xsl:with-param name="j">
                                <xsl:value-of select="$j - 1"/>
                        </xsl:with-param>                        
                        <xsl:with-param name="count">
                                <xsl:value-of select="$count"/>
                        </xsl:with-param>                        
                        <xsl:with-param name="stringop"><xsl:value-of select="$stringop"/></xsl:with-param> 
                        <xsl:with-param name="stringcl"><xsl:value-of select="$stringcl"/></xsl:with-param>                                                                         
                    </xsl:call-template>                
                   </xsl:when>
                   <xsl:when test="preceding-sibling::m:mo[(.)=$stringop or (.)=$stringcl][$i + 1] = $stringcl">
                                    <xsl:call-template name="for.clloop">
                        <xsl:with-param name="i">
                                <xsl:value-of select="$i + 1"/>
                        </xsl:with-param>
                        <xsl:with-param name="j">
                                <xsl:value-of select="$j + 1"/>
                        </xsl:with-param>                        
                        <xsl:with-param name="count">
                                <xsl:value-of select="$count"/>
                        </xsl:with-param>                        
                        <xsl:with-param name="stringop"><xsl:value-of select="$stringop"/></xsl:with-param> 
                        <xsl:with-param name="stringcl"><xsl:value-of select="$stringcl"/></xsl:with-param>                                                                         
                    </xsl:call-template>                
                  </xsl:when>                
                  <xsl:otherwise/>
                  </xsl:choose>
                </xsl:otherwise>                
                </xsl:choose>
        </xsl:if>
</xsl:template>

</xsl:stylesheet>
于 2014-01-12T14:38:08.900 回答
0

这些 Stack Overflow 问题可能会有所帮助

您可以使用此模板将父子元素转换为组合元素:

<xsl:template match="parent">
  <combined>
    <xsl:copy-of select="@* | child/@*" />
  </combined>
</xsl:template>

<parent>这样做是将输入元素及其中的所有属性复制<child>到输出<combined>元素中。

您还需要标识模板,以便通过以下方式传递<data>元素和其他节点:

<xsl:template match="node() | @*">
  <xsl:copy>
    <xsl:apply-templates select="node() | @*" />
  </xsl:copy>
</xsl:template>
于 2013-05-22T05:57:51.843 回答
0

这是一个快速有点脏的解决方案。
这也应该适用于嵌套大括号,但如果大括号在输入中不匹配,则会生成格式不正确的 xml。试试这个:<

?xml version='1.0'?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:m="http://www.w3.org/1998/Math/MathML"
    xmlns="http://www.w3.org/1998/Math/MathML"
    exclude-result-prefixes="m">

    <xsl:output method="xml"/>

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

    <xsl:template match="m:mo[.=')']" >
        <xsl:text disable-output-escaping="yes"><![CDATA[</mfenced>]]></xsl:text>
    </xsl:template>

    <xsl:template match="m:mo[.='(']" >
        <xsl:text disable-output-escaping="yes"><![CDATA[<mfenced>]]></xsl:text>
    </xsl:template>
</xsl:stylesheet>
于 2013-05-22T07:16:53.920 回答