基于XSD的XML导航与内容交叉验证可行性及实现咨询
问题:导航与内容的交叉验证实现可行性及方法
我正在开发一个项目,需要实现导航与内容的交叉验证——确保导航中的所有链接都对应内容模块里真实存在的资源。目前我采用相对路径定义dir和href属性(保证不会链接到章节外的内容),也可以改用XPath方式,但更倾向保留现有格式。
核心要求:
- XML必须能通过XSD(或DTD)验证,因为使用的是跨平台验证器
- 导航模块与内容模块必须分离
- 章节和项支持通过
label="xyz"属性设置标题
我已经有约束严格的XSD,但缺少交叉验证功能,想确认这个需求是否可行,以及具体的实现方法。
示例XML结构
<?xml version="1.0" encoding="UTF-8" ?> <something> <content> <doc src="toc.html" /> <dir name="chapter_1"> <dir name="subchapter_1"> <img src="bbbbb.jpg" /> <img src="cccc.jpg" /> <img src="dddd.jpg" /> </dir> </dir> </content> <navigation> <item label="Start reading" href="/chapter_1/subchapter_1/bbbbb.jpg" /> <chapter label="Chapter 1" dir="/chapter_1" href="/subchapter_1/bbbbb.jpg"> <chapter label="Chapter 1.1" dir="/subchapter_1" href="/bbbbb.jpg" /> </chapter> </navigation> </something>
解决方案
可行性说明
这个需求完全可行。XSD 1.0本身不支持跨节点的交叉验证,但可以通过XSD 1.1的断言(Assertion)或者Schematron规则实现,两种方式都能满足跨平台验证的要求。
具体实现方法
方法一:使用XSD 1.1的断言(推荐,若验证器支持XSD 1.1)
XSD 1.1新增的<xs:assert>元素允许编写XPath表达式,直接在XSD中定义交叉验证规则,无需额外工具。
以下是在现有XSD基础上添加的交叉验证断言示例:
<xs:element name="something"> <xs:complexType> <xs:sequence> <xs:element name="content" type="contentType"/> <xs:element name="navigation" type="navigationType"/> </xs:sequence> <!-- 交叉验证规则 --> <!-- 验证所有item的href对应content中存在的资源 --> <xs:assert test="every $item in navigation/item satisfies exists(content//*[concat('/', string-join(ancestor-or-self::dir/@name, '/'), '/', @src) = $item/@href])"/> <!-- 验证chapter的dir对应content中存在的dir节点 --> <xs:assert test="every $chapter in navigation/chapter//chapter satisfies exists(content//dir[@name = substring-after($chapter/@dir, '/')])"/> <!-- 验证chapter的href对应其dir下的资源 --> <xs:assert test="every $chapter in navigation/chapter//chapter satisfies exists(content//dir[@name = substring-after($chapter/@dir, '/')]//*[@src = substring-after($chapter/@href, '/')])"/> </xs:complexType> </xs:element> <!-- 此处保留你已定义的contentType和navigationType结构 -->
方法二:使用Schematron规则(兼容XSD 1.0,跨平台性更好)
如果你的验证器不支持XSD 1.1,Schematron是更通用的选择——它可以和XSD配合使用,专门处理这类跨节点的验证逻辑。
编写Schematron规则文件(如cross-validation.sch)
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron"> <sch:pattern name="导航与内容交叉验证规则"> <!-- 验证item的href对应content中的资源 --> <sch:rule context="navigation/item"> <sch:assert test="exists(../../content//*[concat('/', string-join(ancestor-or-self::dir/@name, '/'), '/', @src) = current()/@href])"> 导航项href「{@href}」未在内容模块中找到对应资源 </sch:assert> </sch:rule> <!-- 验证chapter的dir对应content中的dir节点 --> <sch:rule context="navigation/chapter"> <sch:assert test="exists(../../content//dir[@name = substring-after(@dir, '/')])"> 章节dir「{@dir}」未在内容模块中找到对应目录 </sch:assert> </sch:rule> <!-- 验证chapter的href对应其目录下的资源 --> <sch:rule context="navigation/chapter"> <sch:assert test="exists(../../content//dir[@name = substring-after(@dir, '/')]//*[@src = substring-after(@href, '/')])"> 章节href「{@href}」未在对应目录下找到资源 </sch:assert> </sch:rule> </sch:pattern> </sch:schema>
使用流程
- 先用你已有的XSD验证XML的结构合法性
- 再用支持Schematron的验证工具(如Saxon、Xerces)加载上述规则文件,对XML进行交叉验证
内容的提问来源于stack exchange,提问作者koallalays
相关产品推荐
相关产品推荐

