Java Проверка XSD зависит от того, предоставляются ли XSD заказа - PullRequest
0 голосов
/ 15 апреля 2020

Имеются два файла схемы XSD:

a.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="b.xsd"/>
    <xs:element name="TestMessage">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="TestSubItem"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

b.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="TestSubItem">
        <xs:complexType>
            <xs:attribute name="name" use="required">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:enumeration value="test"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:attribute>
        </xs:complexType>
    </xs:element>
</xs:schema>

Следующий код java успешно проверяется по схемам :

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.xml.XMLConstants;
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.apache.commons.io.FileUtils;
import org.xml.sax.SAXException;

try
{
    String xsdDirectory = "C:\\XSDFiles";
    String xmlString = "<TestMessage xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> <TestSubItem name=\"test\"/> </TestMessage>";

     Collection<File> xsdFiles = FileUtils.listFiles(new File(xsdDirectory), new String[] { "xsd", "XSD" }, false);
    List<Source> sourceList = new ArrayList<>();
    for (File xsdFile: xsdFiles) {
        sourceList.add(new StreamSource(xsdFile));
    }
    SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

    // 0 then 1, so add a.xsd then b.xsd (alphabetical)
    Schema schema = factory.newSchema(new Source[] {sourceList.get(0), sourceList.get(1)});
    Validator validator = schema.newValidator();
    validator.validate(new StreamSource(new StringReader(xmlString)));
    System.out.println("valid");
}
catch (SAXException e)
{
    System.out.println(e.toString());
}

Но, если вы поменяете местами порядок, схемы будут добавлены в массив Source, так что XSD будут добавлены в обратном порядке (b перед a):

Schema schema = factory.newSchema(new Source[] {sourceList.get(1), sourceList.get(0)});

, тогда вы получите следующее исключение:

org. xml .sax.SAXParseException; номер строки: 1; номер столбца: 68; cv c -elt.1.a: не удается найти объявление элемента 'TestMessage'.

Это нормально, потому что это произвольный пример - но если я загружаю файлы из директории и не знаю «правильный порядок сортировки», тогда как мне заставить код искать элемент root во всех файлах, а не только в первом, который он находит?

1 Ответ

1 голос
/ 15 апреля 2020

Javado c из newSchema(Source[] schemas):

парсеры могут игнорировать все, кроме первого <import> для заданного пространства имен

Прочитайте полное описание в javado c для получения дополнительной информации о контексте.

Таким образом, используется только первый указанный файл.

Поскольку a.xsd имеет <xs:include> для b.xsd, они оба загружаются, когда a.xsd первый.

Если b.xsd первый, то загружается только b.xsd, что означает, что <xs:element name="TestMessage"> отсутствует, а значит и ошибка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...