我希望从<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>
答案 0 :(得分: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 > '0'">
<xsl:text disable-output-escaping="yes"><mfenced separators="" open="</xsl:text>
<xsl:value-of select="$stringop"/>
<xsl:text disable-output-escaping="yes">" close=""></mfenced></xsl:text>
</xsl:if>
<xsl:if test="$j = '0'">
<xsl:text disable-output-escaping="yes"><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">"></xsl:text>
</xsl:if>
</xsl:if>
<xsl:if test="$i < $count">
<xsl:choose>
<xsl:when test="$j = '0'">
<xsl:text disable-output-escaping="yes"><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">"></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 > '0'">
<xsl:text disable-output-escaping="yes"><mfenced separators="" open="" close="</xsl:text>
<xsl:value-of select="$stringcl"/>
<xsl:text disable-output-escaping="yes">"></mfenced></xsl:text>
</xsl:if>
<xsl:if test="$j = '0'">
<xsl:text disable-output-escaping="yes"></mfenced></xsl:text>
</xsl:if>
</xsl:if>
<xsl:if test="$i < $count">
<xsl:choose>
<xsl:when test="$j = '0'">
<xsl:text disable-output-escaping="yes"></mfenced></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>
答案 1 :(得分:0)
这些Stack Overflow问题可能会有所帮助
您可以使用此模板将parent-with-child转换为组合元素:
<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>
答案 2 :(得分:0)
这里有快速和小脏解决方案 这也适用于嵌套大括号,但如果大括号在输入中不匹配,则会生成格式不正确的xml。 试试这个: &LT;
?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>