XSD - 如何允许元素以任何顺序排列,而一些元素出现次数为 0-1 而另一些元素出现次数为 0-unbounded

问题描述 投票:0回答:0

我必须根据 xsd 语法验证 xml 文件。以下是对我的原始需求的简单模拟。

有一个名为

<foo>
的根元素 它有四个子元素,为了简单起见,我们将它们表示为 child1、child2、child3 和 child4。

  • 元素child1 child2可以出现任意次数(0到无界)
  • 任何顺序的元素
  • 元素 child3 和 child4 最多出现一次。 (0 到 1)
  • 所有的子元素都是可选的,从而使
    <foo />
    成为一个有效的xml。

在浏览了一些现有的答案后,我发现 [1] 中给出的更详细的答案 不是我的问题的实际解决方案,因为有超过 10 个子元素 会产生组合爆炸。然后,在答案的后半部分指出 xsd 1.1 放宽了一些限制,因此允许使用

<xs:all>
maxOccurs="unbounded"

然后我使用 xerces 库,并尝试将 xsd 1.1 功能与 java 一起使用。以下是我的示例代码。然而, 当 xml 中存在多个元素时,出现以下错误。 cvc-complex-type.2.4.a:发现以元素“child1”开头的无效内容。需要“{child2, child3, child4}”之一。

带有 xsd 1.1 扩展的 xsd 模式。

<?xml version="1.1" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
    elementFormDefault="qualified" vc:minVersion="1.1">
    <xs:element name="foo">
        <xs:complexType>
            <xs:all>
                <xs:element name="child1" vc:minOccurs="0"
                    vc:maxOccurs="unbounded" />
                <xs:element name="child2" vc:minOccurs="0"
                    vc:maxOccurs="unbounded" />
                <xs:element name="child3" type="xs:string" />
                <xs:element name="child4" type="xs:string" />
            </xs:all>
        </xs:complexType>
    </xs:element>
</xs:schema>

xml有效负载

<foo>
    <child1> a </child1>
    <child1> b </child1>
    <child3> c </child3>
    <child2> d </child2>
    <child4> e </child4>
    <child2> g </child2>
    <child1> f </child1>
</foo>

maven 依赖

                    <dependency>
                        <groupId>org.opengis.cite.xerces</groupId>
                        <artifactId>xercesImpl-xsd11</artifactId>
                        <version>2.12-beta-r1667115</version>
                        <exclusions>
                            <exclusion>
                                <groupId>xml-apis</groupId>
                                <artifactId>xml-apis</artifactId>
                            </exclusion>
                        </exclusions>
                    </dependency>
                    <dependency>
                        <groupId>org.exist-db.thirdparty.org.eclipse.wst.xml</groupId>
                        <artifactId>xpath2</artifactId>
                        <version>1.2.0</version>
                        <scope>runtime</scope>
                    </dependency>
                    <dependency>
                        <groupId>edu.princeton.cup</groupId>
                        <artifactId>java-cup</artifactId>
                        <version>10k</version>
                        <scope>runtime</scope>
                    </dependency>

            <dependency>
                <groupId>org.ibissource</groupId>
                <artifactId>ibis-xerces</artifactId>
                <version>2.12.2-xml-schema-1.1</version>
            </dependency>

示例 java 代码:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.StringJoiner;

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class CrtDataValidatorImpl {

    public void validate(String xsdFilePath, String data) {
        final XmlErrorHandler errorHandler = new XmlErrorHandler();
        try {
            final File schemaFile = new File(xsdFilePath);
            final SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/XML/XMLSchema/v1.1");
            final Schema schema = schemaFactory.newSchema(schemaFile);
            final Validator validator = schema.newValidator();
            validator.setErrorHandler(errorHandler);
            final Source xmlSource = new StreamSource(new StringReader(data));
            validator.validate(xmlSource);
        } catch (SAXException e) {
            System.out.println(e.getMessage());
        } catch (IOException e) {
        }
        System.out.println(String.format("Number of errors: %s", errorHandler.getExceptions().size()));
        for (Exception ex : errorHandler.getExceptions())
            System.out.println(ex.getMessage());
    }

    public static void main(String[] args) throws IOException {
        try (BufferedReader br = new BufferedReader(new FileReader("./src/main/resources/simple-payload.xml"))) {
            final StringJoiner sj = new StringJoiner("\n");
            String line = br.readLine();

            while (line != null) {
                sj.add(line);
                line = br.readLine();
            }
            System.out.println(sj.toString());
            new CrtDataValidatorImpl().validate("./src/main/resources/sample.xsd", sj.toString());
        }
    }

    static class XmlErrorHandler implements ErrorHandler {

        private Collection<SAXParseException> exceptions;

        public XmlErrorHandler() {
            this.exceptions = new ArrayList<>();
        }

        public Collection<SAXParseException> getExceptions() {
            return exceptions;
        }

        @Override
        public void warning(SAXParseException exception) {
            exceptions.add(exception);
        }

        @Override
        public void error(SAXParseException exception) {
            exceptions.add(exception);
        }

        @Override
        public void fatalError(SAXParseException exception) {
            exceptions.add(exception);
        }
    }
}

我尝试调试这个问题,不幸的是,它并没有为找出原因提供任何帮助。这里缺少什么?任何帮助,将不胜感激。谢谢。

[1] XSD - 如何允许任意顺序的元素任意次数?

java xml xsd schema xerces
© www.soinside.com 2019 - 2024. All rights reserved.