使用Schematron QuickFix标记混合内容元素中的单个单词

时间:2015-07-28 07:36:23

标签: xslt-2.0 tokenize xpath-2.0 schematron

我有一个看起来像这样的xml文件(简化):

<defs>
    <def>Pure text</def>
    <def>Mixed content, cuz there is also another: <element>element inside</element> and more.</def>
    <def><element>Text nodes within elements other than def are ok.</element></def>
<defs>

我正在尝试编写一个带有快速修复的Shematron规则,这些规则可以让我在defs中使用混合内容包含每个单词,并将它们分别包含在<w>个元素中,并在{{1}中包装标点字符元素。换句话说,在应用快速修复后,我会得到

<pc>

<defs> <def>Pure text.</def> <def><w>Mixed</w> <w>content</w><pc>,</pc> <w>cuz</w> <w>there</w> <w>is</w> <w>also</w> <w>another</w><pc>:</pc> <element>element inside</element> <w>and</w> <w>more</w><pc>.</pc></def> <def><element>Text nodes within elements other than def are ok.</element></def> <defs> <w>之间的空格都可以。

现在,识别混合内容很容易 - 我认为我做对了。问题是我不知道如何在Schematron中对字符串进行标记,然后对每个标记应用修复。这就是我已经走了多远:

<pc>

任何提示都将不胜感激。

坦奇

1 个答案:

答案 0 :(得分:2)

你可以使用XSL,看看这个例子(在代码注释中解释):

<sch:pattern id="mixed">
    <!-- Your context is now def => this makes easier add new def reports -->
    <sch:rule context="def">

        <!-- So now you report every def that has text and elements -->
        <sch:report test="child::text() and child::*" sqf:fix="mix_in_def">
            Element has mixed content
            <!-- What you were doing before where causing error because you were passing a sequence of text nodes to tokenize (it expects a string) -->
        </sch:report>

        <sqf:fix id="mix_in_def">
            <sqf:description>
                <sqf:title>Wrap words in w</sqf:title>
                <sqf:p>Fixes the mixed content in def by treating each non-tagged string as w.</sqf:p>
            </sqf:description>

            <!-- Replace every mixed text node of this def (this is called for every matched node) -->
            <sqf:replace match="child::text()">
                    <!-- Tokenize this text node => for each token choose... -->
                    <xsl:for-each select="tokenize(., '\s+')">
                        <!-- For this token choose -->
                        <xsl:choose>
                            <!-- If text is one of this (,.:) Please note that you are using \s+ to separate tokens. So a comma is only a token if it is separated by spaces -->
                            <xsl:when test=". = (',', '.', ':', 'is')"> <!-- "is" just to test results -->
                                <pc><xsl:value-of select="."/></pc>
                            </xsl:when>
                            <!-- Otherwise wrap it in <w> -->
                            <xsl:otherwise>
                                <w><xsl:value-of select="."/></w>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:for-each>
            </sqf:replace>

        </sqf:fix>
    </sch:rule>
</sch:pattern>

您必须根据具体问题进行调整,但我认为这会对您有所帮助。