【问题标题】:Using Schematron QuickFixes to tag individual words in mixed content elements使用 Schematron QuickFixes 标记混合内容元素中的单个单词
【发布时间】:2015-07-28 07:36:22
【问题描述】:

我有一个看起来像这样的 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 中的每个单词都包含在 &lt;w&gt; 元素中,并将标点符号包含在 &lt;pc&gt; 元素中。换句话说,在应用快速修复后,我会得到

<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>

&lt;w&gt;s 和 &lt;pc&gt;s 之间的空格是可以的。

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

<sch:pattern id="mixed">
    <sch:rule context="def[child::text()][child::*]">
        <sch:report test="tokenize(child::text(), '\s+')" sqf:fix="mix_in_def">
            Element has mixed content
            <!-- the above this gives me the error: a sequence of more than one item is not allowed as the first argument of tokenize-->
        </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>
            <sqf:replace match="." node-type="element" target="w">
                <!--how do i represent the content of the matched token?-->
            </sqf:replace>
            <!-- also do i create an altogether separate rule for punctuation?-->
        </sqf:fix>
    </sch:rule>
</sch:pattern>

任何提示将不胜感激。

丁丁

【问题讨论】:

  • 我的回答对您有帮助吗?
  • 我还在等待一些反馈,请告诉我我的回答是否有用。
  • 绝对。我真的很抱歉我没有承认你的回答。我的错。
  • 这很有帮助 :D 没有反馈,我在想你可能在我的回答中发现了问题,我想知道哪里出了问题。

标签: xslt-2.0 tokenize xpath-2.0 schematron


【解决方案1】:

可以使用XSL,看这个例子(代码cmets中有说明):

<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>

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

【讨论】:

  • 有趣的建议,@sergioFC!您是否知道在哪里可以找到有关将 XSLT 与 Schematron 规则混合使用的更多信息?我可以在Schematron ISO documentation 的“XSLT 2 的查询语言绑定”部分找到最具体的指针。在那里,&lt;xsl:key&gt;&lt;xsl:function&gt;&lt;xsl:copy-of&gt;&lt;sch:pattern&gt; 元素之前被提及为允许的内容,但到目前为止我还没有在 XSLT 指令 inside 模式中找到任何内容。但它正在工作,因此必须允许。
  • 谢谢。恐怕我不能提供文件。正如我所看到的,Schematron 规范说您可以定义自己的自定义xsl:function,以便以后重用它们。请参阅此xsl:function inside Schematron example。我对这篇文章的回答中的 XSLT 代码是 Schematron QuickFix 规范的一部分,它不是 Schematron 规范本身的一部分。 Schematron QuickFix 是在 Schematron 几年后创建的,目的是允许 XML 修复 Schematron 可以报告的问题,但它是 Schematron 的扩展,而不是它的一部分
  • 好的,感谢您阐明 SQF 上下文。然而,我尝试将其精简(参见sample files in this gist),它确实似乎也可以在 Schematron ns 中工作:各种 XSLT 指令只是在 Schematron 模式中愉快地执行.就我的目的而言,这真是太好了,但我想知道我是否对某个功能或错误(规范或实现)感到兴奋。我只是想向您指出这一点,但会尝试找到一个更合适的论坛来充实这一点。
  • 你是对的,现在我明白你在说什么了。我看到任何 XSL 似乎都是有效的,但我不知道这是否应该是预期的行为。也许它与一些使用 XSL 骨架转换的 Schematron 实现有关
猜你喜欢
  • 1970-01-01
  • 2015-06-06
  • 2021-09-19
  • 1970-01-01
  • 2015-05-22
  • 1970-01-01
  • 2016-08-30
  • 1970-01-01
相关资源
最近更新 更多