Используя xsl для вывода математического выражения
Я хочу использовать xslt для вывода математического выражения из ввода Mathml. Там должно быть какая-то ошибка в моем преобразовании. Я не знаю, как это исправить. Не могли бы вы помочь мне? Должен ли я использовать параметр или переменную для управления им? XML:
<?xml version="1.0" encoding="UTF-8"?>
<math>
<apply>
<eq/>
<apply>
<plus/>
<apply>
<power/>
<ci>x</ci>
<cn>2</cn>
</apply>
<apply>
<times/>
<cn>2</cn>
<ci>x</ci>
</apply>
<cn>2</cn>
</apply>
<cn>0</cn>
</apply>
</math>
Это мой xsl:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/">
<xsl:apply-templates/>
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template match="math">
<xsl:apply-templates select="apply"/>
</xsl:template>
<xsl:template match="apply">
<xsl:sequence select="name(element()[1]),'('"/>
<xsl:apply-templates select="apply">
</xsl:apply-templates>
<xsl:sequence select="element()[2],','"/>
<xsl:sequence select="element()[3],')',','"/>
</xsl:template>
</xsl:stylesheet>
Результат должен быть:
экв (плюс (мощность (х,2), раз (2, х),2),0)
2 ответа
Это полное и короткое преобразование:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="apply">
<xsl:if test="not(position()=1)">,</xsl:if>
<xsl:apply-templates select="*[1]"/>
</xsl:template>
<xsl:template match="eq|plus|power|times">
<xsl:if test="not(position()=1)">,</xsl:if>
<xsl:value-of select="concat(name(), '(')"/>
<xsl:apply-templates select="following-sibling::*"/>
<xsl:text>)</xsl:text>
</xsl:template>
<xsl:template match="cn|ci">
<xsl:if test="not(position()=1)">,</xsl:if>
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному документу XML:
<math>
<apply>
<eq/>
<apply>
<plus/>
<apply>
<power/>
<ci>x</ci>
<cn>2</cn>
</apply>
<apply>
<times/>
<cn>2</cn>
<ci>x</ci>
</apply>
<cn>2</cn>
</apply>
<cn>0</cn>
</apply>
</math>
дать желаемый, правильный результат:
eq(plus(power(x,2),times(2,x),2),0)
Я немного изменил исходное преобразование, чтобы получить желаемый результат. В основном, apply
шаблонное правило - это то, что решает для функции парентез. Чтобы определить, стоит ли вставлять запятую, я проверяю наличие следующих родственных элементов определенных типов.
Кроме того, я заменил ваш xsl:sequence
с xsl:value-of
таким образом предотвращая создание нежелательных пространств (я предполагаю, что они нежелательны). Также функция element()
был заменен. Таблица стилей теперь совместима с XSLT 1.0. Мне не нравится XSLT 1.0, но я предпочитаю использовать новые функции только тогда, когда это действительно необходимо.
Это решение не очень общее (MATHML - огромная спецификация, которую вы знаете), но вы можете использовать его и адаптировать к более сложным случаям.
XSLT 1.0 протестирован под Saxon 6.5.5
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="apply">
<xsl:value-of select="concat(name(child::*[1]),'(')"/>
<xsl:apply-templates select="apply|cn|ci"/>
<xsl:value-of select="')'"/>
<xsl:if test="count(following-sibling::*)">
<xsl:value-of select="','"/>
</xsl:if>
</xsl:template>
<xsl:template match="cn|ci">
<xsl:value-of select="."/>
<xsl:if test="count(following-sibling::*)>0">
<xsl:value-of select="','"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Применительно к входу, указанному в вопросе, получается:
eq(plus(power(x,2),times(2,x),2),0)