我们如何在 schematron 错误消息输出中添加 xpath 信息



我在MarkLogic中使用schematron API来验证XML文档。下面是供参考的代码片段。

xquery version "1.0-ml";
import module namespace sch = "http://marklogic.com/validate" at 
"/MarkLogic/appservices/utils/validate.xqy";
import module namespace transform = "http://marklogic.com/transform" at "/MarkLogic/appservices/utils/transform.xqy";
declare namespace xsl = "http://www.w3.org/1999/XSL/not-Transform";
declare namespace iso = "http://purl.oclc.org/dsdl/schematron";

let $document :=
document{
<book xmlns="http://docbook.org/ns/docbook">
<title>Some Title</title>
<chapter>
<para>...</para>
</chapter>
</book>
}
let $schema := 
<s:schema xmlns:s="http://purl.oclc.org/dsdl/schematron"
xmlns:db="http://docbook.org/ns/docbook">
<s:ns prefix="db" uri="http://docbook.org/ns/docbook"/>
<s:pattern name="Glossary 'firstterm' type constraint">
<s:rule context="db:chapter">
<s:assert test="db:title">Chapter should contain title</s:assert>
</s:rule>
</s:pattern>
</s:schema>
return
sch:schematron($document, $schema)

任何人都可以帮助我获取上下文节点的 XPath 信息以及 schematron 错误消息输出。

这是我认为您要求的代码。

如果你想要一个项目的xpath,你可以使用xdmp:path。 为了获得整个文档的 xpath,你只需要遍历树,这就是递归函数local:getXpathDeep正在做的事情。您可以从我使用的string-join更改输出的格式,它只是使我更容易阅读。我创建了一个 XML 输出来将 schematron 结果和 XPath 放入其中,但如果您愿意,您可以返回一个序列或将其放入映射中。

xquery version "1.0-ml";
import module namespace sch = "http://marklogic.com/validate" at 
"/MarkLogic/appservices/utils/validate.xqy";
import module namespace transform = "http://marklogic.com/transform" at "/MarkLogic/appservices/utils/transform.xqy";
declare namespace xsl = "http://www.w3.org/1999/XSL/not-Transform";
declare namespace iso = "http://purl.oclc.org/dsdl/schematron";
declare function local:getXpathDeep($node){
(
xdmp:path($node), 
if (fn:exists($node/*)) then (
local:getXpathDeep($node/*)
) else ()
)
};
let $document :=
document{
<book xmlns="http://docbook.org/ns/docbook">
<title>Some Title</title>
<chapter>
<para>...</para>
</chapter>
</book>
}
let $schema := 
<s:schema xmlns:s="http://purl.oclc.org/dsdl/schematron"
xmlns:db="http://docbook.org/ns/docbook">
<s:ns prefix="db" uri="http://docbook.org/ns/docbook"/>
<s:pattern name="Glossary 'firstterm' type constraint">
<s:rule context="db:chapter">
<s:assert test="db:title">Chapter should contain title</s:assert>
</s:rule>
</s:pattern>
</s:schema>
return
<result>
<contextNodeXpath>{fn:string-join(local:getXpathDeep($document), " 
" )}</contextNodeXpath>
<schematronOutPut>{sch:schematron($document, $schema)}</schematronOutPut>
</result>

该特定的 Schematron 模块相当有限,并且不提供从报告或失败断言返回上下文节点的 XPath 的方法。

标准 Schematron SVRL 输出确实包括触发失败断言或报告的项的 XPath。

Norm Walsh 发布了 ML-Schematron 模块,该模块使用 Schematron 样式表将 Schematron 模式的编译包装到 XSLT 中,并随后执行编译的 XSLT 以生成 SVRL 报告。

您可以调整模块以使用它(在安装它和模块数据库中的标准 Schematron XSLT 文件之后(:

xquery version "1.0-ml";
declare namespace svrl="http://purl.oclc.org/dsdl/svrl";
import module namespace sch="http://marklogic.com/schematron" at "/schematron.xqy";
let $document :=
document{
<book xmlns="http://docbook.org/ns/docbook">
<title>Some Title</title>
<chapter>
<para>...</para>
</chapter>
</book>
}
let $schema := 
<s:schema xmlns:s="http://purl.oclc.org/dsdl/schematron"
xmlns:db="http://docbook.org/ns/docbook">
<s:ns prefix="db" uri="http://docbook.org/ns/docbook"/>
<s:pattern name="Glossary 'firstterm' type constraint">
<s:rule context="db:chapter">
<s:assert test="db:title">Chapter should contain title</s:assert>
</s:rule>
</s:pattern>
</s:schema>
return
sch:validate-document($document, $schema)

它生成以下 SVRL 报告,其中包括位置属性/*[local-name()='book']/*[local-name()='chapter']中的 XPath:

<svrl:schematron-output title="" schemaVersion="" xmlns:schold="http://www.ascc.net/xml/schematron" 
xmlns:iso="http://purl.oclc.org/dsdl/schematron" xmlns:xhtml="http://www.w3.org/1999/xhtml" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:db="http://docbook.org/ns/docbook" xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias" 
xmlns:svrl="http://purl.oclc.org/dsdl/svrl">
<!---->
<svrl:ns-prefix-in-attribute-values uri="http://docbook.org/ns/docbook" prefix="db"/>
<svrl:active-pattern document=""/>
<svrl:fired-rule context="db:chapter"/>
<svrl:failed-assert test="db:title" location="/*[local-name()='book']/*[local-name()='chapter']">
<svrl:text>Chapter should contain title</svrl:text>
</svrl:failed-assert>
</svrl:schematron-output>

最新更新