analyze-string:嵌套到plain返回嵌套

时间:2018-04-18 18:53:32

标签: regex xslt

这可能是一个奇怪的问题,但我很好奇是否有解决方案。我有一个深度嵌套和复杂的XML文件,例如OOXML和我尝试用一​​些正则表达式来分析它的文本。

分析文档的文本我想(1)将所有文本节点存储在变量中,(2)运行一些正则表达式,(3)将所有文本节点写回其原始元素。显然最后一部分是问题,我不知道它是否可能。

(简化)XML:

<?xml version="1.0" encoding="UTF-8"?>
<body>
    <p>
        <t>foo </t>
        <t>some text </t>
        <t>
            <i>number</i>
            <b>
                <nr>5</nr>
            </b>
        </t>
        <t>more </t>
        <t>text</t>
    </p>
</body>

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:template match="p">
        <xsl:variable name="plain" select="normalize-space(string-join(t//text(), ''))"/>
        <xsl:analyze-string select="$plain" regex="foo( .* )number (\d)">
            <xsl:matching-substring>
                <xsl:value-of select="'bar', regex-group(1), 'nr.', regex-group(2)"/>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
                <xsl:value-of select="."/>
            </xsl:non-matching-substring>
        </xsl:analyze-string>
    </xsl:template>
</xsl:stylesheet>

通缉输出类似于:

<?xml version="1.0" encoding="UTF-8"?>
<body>
    <p>
        <t>bar </t>
        <t>some text </t>
        <t>
            <i>nr. </i>
            <b>
                <nr>5</nr>
            </b>
        </t>
        <t>more </t>
        <t>text</t>
    </p>
</body>

我知道在这种情况下,t上的模板匹配以及检查precedingfollowing轴的一些XPath可以完成这项工作。但是当XML变得更加复杂时,它会非常烦人。

1 个答案:

答案 0 :(得分:1)

怎么样

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">

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

    <xsl:template match="t[parent::p[matches(normalize-space(string-join(t//text(), '')), 'foo( .* )number (\d)')]]/text()">
        <xsl:value-of select="replace(replace(., 'foo', 'bar'), 'number', 'nr.')"/>
    </xsl:template>

    <xsl:template match="*[ancestor::t]/text()">
        <xsl:value-of select="replace(replace(., 'foo', 'bar'), 'number', 'nr.')"/>
    </xsl:template>

</xsl:stylesheet>

我不知道这是否仍适用于复杂的XML。