使用XSLT将两个元素更改为单个元素

使用XSLT将两个元素更改为单个元素,xslt,Xslt,我想从(到)转换到。。 示例输入如下所示: 示例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>

我想从
转换到
。 示例输入如下所示:

示例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>
<?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>


罪
(
x
Y
)
=
罪
x
罪
Y

XSLT2.0已试用:

<?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>
<?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>

所需输出:

<?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>
<?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>


罪
x
Y
=
罪
x
罪
Y


这些堆栈溢出问题可能会有所帮助

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

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

这样做的目的是将所有属性从输入
元素及其
复制到输出
元素中

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

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


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

]]> ]]>
这是我用于将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>

mfenced分离器=“打开=”
“close=”“/mfenced
mfenced分离器=“打开=”
“关闭=”
"        
mfenced分离器=“打开=”
“关闭=”
"        
mfenced分离器=“打开=”“关闭=”
“/mfenced
/mfenced
/mfenced

如果我假设在最后的xml中可以嵌套大括号,那么我是对的?例如
cos(sin(x)*y)
?@hr_117:所有的左大括号和右大括号中的元素都应该分组到元素中,并且在哪里出现并不重要。但是如果在仍然打开的大括号中允许打开大括号,则可能的解决方案会有所不同。这应该比导致太多嵌套mfenced。而仅对您的上述示例有效的解决方案并没有多大帮助。@hr_117:输出应该嵌套在e.gIs中。有任何其他选项可以维护格式良好的XML。另一种可能是递归遍历以下同级并计算大括号(递增和递减)。即使不匹配大括号,也可以生成格式良好的xml。但在这种情况下,输入仍然是格式良好的xml,但无论如何都是错误的。