2013-05-22 104 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>