XSLT 2.0:使用analyze-string过滤节点/文本,但还需要获取XML标记

时间:2013-05-23 17:43:13

标签: string xpath nodes xslt-2.0 xmlspy

我正在完成我的第一个主要的XSLT项目,并且我是一个新手,所以请耐心等待我的无知。

我们小组正致力于将现有XML转换为完全不同的标记系统。我已经设计了一个使用Analyze-String处理MathType标注(用“$ {TEXT}”表示)的系统,但是我很难确定我应该用ital标签代码做什么(用“I”标签表示),需要保存在结果代码中。

我尝试在非匹配子字符串中使用copy-of,但这似乎不起作用。当然,除了ital标签之外,还有价值。

我意识到变量($ stemString)在这一点上是多余的。我正沿着这条道路走,以为我可能会想出一些可以复制处理的东西,但到目前为止,没有运气。

示例代码:

<stem>What is the value of <I>f</I>(<I>x</I>) when ${##A112800eqn01:3}</stem>

我目前的XSLT:

<?xml version="1.0" encoding="UTF-8"?>

    

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

<xsl:template match="assessmentItem">

<!--SNIP-->

    <xsl:apply-templates select="stemArea/stem"/>

<!--SNIP-->

</xsl:template>

<xsl:template match="stem">

    <xsl:variable name="stemString">
        <xsl:copy-of select="./* | ./text()"/>
    </xsl:variable>

    <xsl:choose>

        <!--Tests for empty stems that aren't art callouts-->
        <xsl:when test=". = '' and @type!='art'"></xsl:when>
        <xsl:when test=". = ' ' and @type!='art'"></xsl:when>

        <!--Test for art callouts-->
        <xsl:when test="@type='art'"><p><img alt="{@loc}" height="10" id="{@loc}" label="" longdesc="normal" src="{@loc}" width="10"/></p></xsl:when>

        <!--Test for boxed text-->
        <xsl:when test="@style='box' or @style='boxL'"><p><span label="Tag_7">
            <xsl:copy-of select="./* | ./text()"></xsl:copy-of>
        </span></p></xsl:when>

        <xsl:otherwise><p>

            <!--Are MathType tokens present in stem?-->
            <xsl:analyze-string regex="(\$\{{.+\}})" select="$stemString">

                <!--If MathType tokens are in stem, do the following-->
                <xsl:matching-substring>

                    <xsl:analyze-string regex="(\$\{{)(##.+[eqn|art]\d+)([^a-zA-Z0-9]?.*\}})" select=".">
                        <xsl:matching-substring>
                            <img alt="{regex-group(2)}" height="10" id="{regex-group(2)}" label="" longdesc="normal" src="{regex-group(2)}" width="10"/>
                        </xsl:matching-substring>
                        <xsl:non-matching-substring>
                            <xsl:text>ERROR</xsl:text>
                        </xsl:non-matching-substring>
                    </xsl:analyze-string>

                </xsl:matching-substring>

                <!--No MathType tokens in string-->
                <xsl:non-matching-substring>
                    <xsl:value-of select="."/>
                </xsl:non-matching-substring>

            </xsl:analyze-string>
        </p></xsl:otherwise>

    </xsl:choose>

</xsl:template>

期望的输出:

<p>What is the value of <I>f</I>(<I>x</I>) when <img alt="##A112800eqn01" height="10" id="##A112800eqn01" label="" longdesc="normal" src="##A112800eqn01" width="10"/></p>

我得到了什么:

<p>What is the value of f(x) when <img alt="##A112800eqn01" height="10" id="##A112800eqn01" label="" longdesc="normal" src="##A112800eqn01" width="10"/></p>

任何人对如何进行有任何想法?

@Martin Honnen:谢谢你的回复。您的代码解决了错误。

但是,我还有一个问题。当一个词干中有多个MathType标注时,会导致错误。我确信原因是我的正则表达不能正常捕捉所有东西,但我已经敲了一段时间无济于事。下面我将说明我遇到的问题。

示例代码:

<stem type="text">What is the value of <I>f</I>(<I>x</I>) when ${##A112800eqn01:3}, and ${##A112800eqn02:3} is 3.</stem>

期望的输出:

<p>What is the value of <I>f</I>(<I>x</I>) when <img alt="##A112800eqn01" height="10" id="##A112800eqn01" label="" longdesc="normal" src="##A112800eqn01" width="10"/>, and <img alt="##A112800eqn02" height="10" id="##A112800eqn02" label="" longdesc="normal" src="##A112800eqn02" width="10"/> is 3.</p>

我得到了什么:

<p>What is the value of <I>f</I>(<I>x</I>) when <img alt="##A112800eqn01:3}, and ${##A112800eqn02" height="10" id="##A112800eqn01:3}, and ${##A112800eqn02" label="" longdesc="normal" src="##A112800eqn01:3}, and ${##A112800eqn02" width="10"/> is 3.</p>

1 个答案:

答案 0 :(得分:2)

在元素上不匹配,然后将xsl:choose放在模板内部以进一步区分,而只是为具有特定属性值的不同元素或元素编写模板。

如果您想使用analyze-string,请在text节点的模板中执行此操作,而不是在包含混合内容的元素的模板中执行此操作:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

<xsl:template match="assessmentItem">

<!--SNIP-->

    <xsl:apply-templates select="stemArea/stem"/>

<!--SNIP-->

</xsl:template>

<xsl:template match="stem[. = '' and @type!='art'] | stem[. = ' ' and @type != 'art']"/>

<xsl:template match="stem[@style='box' or @style='boxL']">
  <p><span label="Tag_7"><xsl:apply-templates/></span></p>
</xsl:template>

<xsl:template match="stem[.//text()[matches(., '\$\{.+\}')]]">
  <p>
    <xsl:apply-templates/>
  </p>
</xsl:template>

<xsl:template match="stem//text()[matches(., '\$\{.+\}')]">
  <xsl:analyze-string regex="(\$\{{)(##.+[eqn|art]\d+)([^a-zA-Z0-9]?.*\}})" select=".">
    <xsl:matching-substring>
      <img alt="{regex-group(2)}" height="10" id="{regex-group(2)}" label="" longdesc="normal" src="{regex-group(2)}" width="10"/>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
        <xsl:value-of select="."/>
    </xsl:non-matching-substring>
  </xsl:analyze-string>
</xsl:template>

</xsl:stylesheet>

使用该样式表,应用于输入

<stem>What is the value of <I>f</I>(<I>x</I>) when ${##A112800eqn01:3}</stem>

我得到了结果

<p>What is the value of <I>f</I>(<I>x</I>) when <img alt="##A112800eqn01" height="10" id="##A112800eqn01" label="" longdesc="normal" src="##A112800eqn01" width="10"/></p>

以上是关于如何处理样式表设计的建议,它可能不是一个完整的解决方案,因为我没有太多的输入样本要测试,也不知道你正在尝试的输入XML和文本格式处理。

我可能会实施

<xsl:template match="stem[. = '' and @type!='art'] | stem[. = ' ' and @type != 'art']"/>

作为

<xsl:template match="stem[not(normalize-space()) and @type!='art']"/>

相反,但我主要尝试展示如何使用模板构造样式表以及如何在stem的后代文本节点上进行匹配,以确保analyze-string不会吞噬{{1}内的元素节点}}。

对于您编辑的输入要求,我已将正则表达式更改为使用非贪婪匹配(stem),因此使用下面的代码,您应该能够匹配{{1}中的多个模式创建多个.*?元素:

stem