2013-05-22 97 views
0

我想从<mo>得到改造(</mo>直到<mo></mo>到 .. </mfenced>更改两个元素成单元素。下面 采样输入给出:使用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> 
     <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> 
+0

我是对的,如果我认为在最终的XML大括号可以嵌套?像例如'cos(sin(x)* y)'? –

+0

@ hr_117:所有的开合花括号及其中的元素都应该组合在元素中,并且它在哪里出现并不重要。 – siva2012

+0

但是,如果在仍然打开的大括号中允许打开大括号,它会使可能的解决方案有所不同。哪个应该比铅太嵌套mfenced。比只适用于上述示例的解决方案不会真的有很大的帮助。 –

回答

0

这些堆栈溢出的问题可以帮助

你可以使用这个模板的父母与孩子转变为组合元素:

<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> 
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> 
+0

,输出应该嵌套mfenced是否有任何其他选项来保持格式良好的XML。 – siva2012

+0

另一种可能性是通过以下兄弟和递归括号(递增和递减)递归地步进。这可以生成格式良好的XML,即使不匹配大括号。但仍然在这种情况下,输入形式良好的XML,但任何方式都是错误的。 –

1

这是我使用的莫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>