问题描述
我有许多复杂的 XSD 文件用于验证传入的 XML。这些 XSD 是标准的,会不时更新。
最重要的是,有一项业务限制规定,任何元素/属性中只允许使用特定的拉丁字符、数字和符号子集。
我的想法不是去每个 XSD 并为每个 simpleType 添加模式限制(由于多种原因,这是不可能的),我的想法是创建一个通用 XSD,在特定 XSD 之前用作一般验证将应用验证。
但是,我无法找到一种方法对可变元素集应用相同的限制,无论它们在何处声明以及声明的深度如何。
为了给您一个想法,我想到使用 xsd:any
并像这样应用相同的 simpleType
:
<!-- XSD for allowable characters -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="AppHdr" type="AnyRoot"/>
<xs:simpleType name="AnyElement">
<xs:restriction base="xs:string">
<xs:pattern value="[A-Za-z0-9]*"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="AnyRoot">
<xs:sequence>
<xs:any namespace="##any" processContents="skip"
minOccurs="0" maxOccurs="unbounded"
type="AnyElement"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
不幸的是,type
中不允许使用 xs:any
属性,因此这是无效的。也许这与 xs:group
的组合可以解决问题?
搜索任何替代方法但没有运气,我发现所有类似的方法都涉及更改具有已知名称和位置的原始 XSD 中的特定元素。这对我来说不行。
起初,我认为这似乎是微不足道的常见情况,但结果证明这是一种罕见的情况。
如果有人能对此有所了解,我将不胜感激。谢谢!
[编辑]:
我最终决定采用另一条路径而不是 XSD,我使用 XSL 来过滤无效字符并在找到后返回报告。
<?xml version="1.0" encoding="UTF-8"?>
<!-- XSL for allowable characters: Andreas Gounaris,2021 -->
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:devdom="http://example.com/xfunctions/"
extension-element-prefixes="devdom">
<xsl:output method="text" media-type="text/plain" indent="no" omit-xml-declaration="yes" encoding="UTF-8"/>
<!-- Matching document root -->
<xsl:template match="/">
<xsl:apply-templates select="*" mode="verify"/>
</xsl:template>
<!-- Remove whitespace between nodes -->
<xsl:template match="text()[not(normalize-space())]" mode="verify"/>
<xsl:template match="*" mode="verify">
<xsl:apply-templates select="@* | node()" mode="verify"/>
</xsl:template>
<!-- Matching attribute and text nodes -->
<xsl:template match="@* | text()" mode="verify">
<xsl:variable name="invalidContent" select="devdom:exslt_verify_mx_disclosure_chars(.)"/>
<xsl:if test="$invalidContent">
<xsl:value-of select="concat(name(parent::*),': ',$invalidContent)"/>
<xsl:value-of select="'|-|'"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
转换器遍历所有属性和文本节点,并以当前节点作为参数调用 XSLT 外部函数 exslt_verify_mx_disclosure_chars
。
该函数匹配正则表达式中任何但有效的字符。
在这个例子中,我返回一个以字符串分隔的文本文件“|-|”但它也可以是 XML。
解决方法
使用 XPath 或 XSLT 2 或 3 的 Schematron 可能类似于
Wanted but not invoked:
activityMainViewModel.getCdfwData();
-> at cerence.assistant.reference.app.ui.activity.main.ActivityMainViewModel.getCdfwData
,
如果这是混合内容,那么您绝对不能这样做(没有 XSD 1.1 断言)- 没有办法限制出现在混合内容中的文本。
对于简单类型,您可以使用适当的模式限制使所有(基于字符串的)简单类型派生自 xs:string 的子类型,但如果重构过多,那么您将拥有寻找另一种方式。
如果您要进行独立于 XSD 验证的单独验证通过,那么 XSD 似乎不是执行此操作的正确技术。如果您在 Java 世界中,我很想使用放置在 XML 解析器和模式验证器之间的 SAX 过滤器来完成。