【发布时间】:2013-02-23 02:10:26
【问题描述】:
我正在尝试做一些不可能的事情。
我有一个包含相同类型记录列表的 XML 文档。像这样的:
<root>
<record>I'm a shark.</record>
<record>I'm a shark.</record>
<record>Suck it.</record>
<record>I'm a shark.</record>
</root>
首先,我通过 XSD 运行它以确保标签正确。然后,我解组它并对实际值进行一些编程验证。我想通过<xs:pattern /> 将第二步折叠到 XSD 中(将值与正则表达式匹配以测试有效性)。
问题是我的业务规则是我应该继续处理 XML 文档中列出的所有有效记录,并且只处理无效的特定记录。在我上面的例子中,我想要让“Suck it”失败。重视并传递所有“我是鲨鱼”。值转发到某些处理步骤以供实际使用。
不幸的是,据我所知,在 XSD 中,如果某个部分失败,则整个文档只是“糟糕”并且无法通过验证。所以,在我上面的例子中,“Suck it”。 value 删除整个文档。有没有办法解决这个问题?我只是坚持我的第二个编程步骤吗?如果我 可以 仅使单个标签而不是整个文档失败,是否有某种方法可以解决“此标签因这个原因而失败”。验证期间?
编辑:我最终使用了 SAXParser 并在其上设置了 Schema,并将扩展 DefaultHandler 的自定义类交给它,该类在某种程度上手动处理 XML。
我在我的自定义 DefaultHandler 内部设置了一个私有类 Node,这是一个非常简单的 Tree 实现。每个Node 都包含一个开始标记、值和结束标记,所有这些都存储为Strings,以及与父级和子级的关系。每当我收到包含以“cvc-pattern-valid”或“cvc-type.3.1.3”(或我想要捕获的任何 XML 错误)开头的消息的 SAXException 时,我都会删除我所在的 Node从我正在建造的树的中间(因为它已经坏了),然后继续前进。然后,当我通过在根(使用各种 StringBuilders)上调用 Node.depthFirstSearch() 完成解析后,我可以将整个文档(减去剔除标签)输出为一个大 XML String。
我现在的问题是,感觉就像我做了大量的工作只是为了将 XML 视为 XML。我必须重新添加“<”、“>”和“<\”字符,因为DefaultHandler 中的方法只给了我像剥离的qName 这样的东西。所有这些树的构建和遍历似乎效率低下;喜欢太多的工作。肯定有更简单的方法吗?
注意:我之所以要将 XML 保留为 XML,是因为这是我以前的工作流程:
XSD -> XSLT -> Unmarshal to JAXB-Annotated Object
现在是这样的:
SAXParser(XSD) -> XSLT -> Unmarshal to JAXB-Annotated Object
也许有一些神奇的方法可以做到:
SAXParser(XSD, XSLT) -> Unmarshal to JAXB-Annotated Object
或者
SAXParser(XSD, XSLT, Unmarshal to JAXB-Annotated Object)
但我不知道那会是什么。
编辑:好吧,除了可能的低效率之外,扩展DefaultHandler,覆盖DefaultHandler.error(SAXParseException exception) 是正确的答案,至少对我来说是这样。因此,Petru 得到了梦寐以求的绿色复选标记。
【问题讨论】:
-
你在哪个平台上?爪哇? .NET?
-
我不知道有任何 xsd 验证器可以满足您的需求。这根本不是 XSD 的设计目的。不过,您可能会为此有效地使用 XSLT。只需使用选择性复制的复制模板即可。
-
@PetruGardea:Java。我主要使用 JAXB,在一些特殊情况下使用一点 Saxon。
-
@StanleyDeBoer:我不能只跳过无效的,我需要具体知道哪些失败,以便生成通知。
标签: xml validation xsd jaxb