【发布时间】:2021-09-13 11:42:17
【问题描述】:
我有许多用于验证传入 XML 的复杂 XSD 文件。这些 XSD 是标准,并且会不时更新。
除此之外,还有一项业务限制规定,任何元素/属性中只能允许使用特定的拉丁字符、数字和符号子集。
我的想法是创建一个通用 XSD,在特定 XSD 之前用作通用验证,而不是去每个 XSD 并为每个 simpleType 添加模式限制(由于多种原因这是不可能的)将应用验证。
但是,我找不到将相同限制应用于可变元素集的方法,无论它们声明的位置和深度。
为了给你一个想法,我想使用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>
很遗憾,xs:any 中不允许使用 type 属性,因此这是无效的。也许这与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。
该函数匹配正则表达式中任何但有效的字符。
在这个例子中,我返回一个 str 分隔的文本文件 '|-|'但它也可以是 XML。
【问题讨论】:
-
它必须是 XSD 1 架构吗?或者您可以使用 Schematron 还是使用带有断言的 XSD 1.1?
-
@MartinHonnen 您的意思是 2 个 XSD 用于第一次验证(允许的字符)?至于您的其他建议,我不希望将其他框架放入图片中,这会增加额外的工作量(学习曲线、实施、资源),因为此过程只是要求极高的消息传递服务管道中的一小部分。谢谢你的建议,我去看看。
-
好吧,作为最后的手段,我正在考虑编写一小段 XSLT 来转换 XML 并在验证失败时输出成功消息或有问题的元素列表。但是,我想知道这是否可以使用 XSD。