Как обеспечить правильную проверку разных версий XSD? - PullRequest
2 голосов
/ 08 июня 2011

Я пытаюсь обновить некоторые синтаксические анализаторы xml и обнаружил небольшую ошибку. У нас есть xsd, который нам нужен для совместимости со старыми версиями xml, и нам пришлось внести в него некоторые изменения. Мы внесли изменения в новую версию xsd, и мы хотели бы использовать один и тот же парсер (поскольку изменения в целом довольно малы, и парсер может легко справиться с обоими). Мы используем XMLReader свойство "http://java.sun.com/xml/jaxp/properties/schemaSource", чтобы установить схему на предыдущую версию, используя что-то вроде следующего:

xmlReader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", 
    new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.0.xsd")));

Это работало нормально, когда у нас была только одна версия схемы. Теперь у нас есть новая версия, и мы хотим, чтобы система использовала ту версию схемы, которая определена во входящем xml. Обе схемы определяют пространство имен, что-то вроде следующего:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.mycompany.com/my-xsd-1.0"
    xmlns="http://www.mycompany.com/my-xsd-1.0"
    elementFormDefault="unqualified" attributeFormDefault="unqualified">

и, для нового:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.mycompany.com/my-xsd-1.1"
    xmlns="http://www.mycompany.com/my-xsd-1.1"
    elementFormDefault="unqualified" attributeFormDefault="unqualified">

Таким образом, они имеют разные пространства имен и разные "местоположения" схемы. Мы не хотим, чтобы схема работала в сети - мы хотим, чтобы она была связана с нашей системой. Есть ли способ использовать механизм setProperty для такого поведения или есть другой способ справиться с этим?

Я попытался поместить оба ресурса во входной поток в массиве в качестве параметра, но это не сработало (я помню, как где-то читал, что это было возможным решением - хотя сейчас я не могу найти источник, поэтому он может было желаемое за действительное).

Ответы [ 2 ]

2 голосов
/ 10 июня 2011

Итак, получается, что я действительно пытался сработать - мы случайно использовали недопустимый xml! Что работает (для всех, кто заинтересован) следующее:

List<InputSource> inputs = new ArrayList<InputSource>();
inputs.add(new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.0.xsd")));
inputs.add(new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.1.xsd")));

xmlReader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", 
    inputs.toArray(new InputSource[inputs.size()]));
1 голос
/ 08 июня 2011

Лично я думаю, что вообще плохая идея менять пространство имен при создании версии схемы, если только изменения не радикальны - но мнения по этому поводу расходятся, и вы, кажется, приняли свое решение, и вы также можете воспользоваться преимуществами.

Поскольку вы используете два разных пространства имен, схемы, по-видимому, не пересекаются, поэтому вы должны быть в состоянии дать процессору схему, которая объединяет два - я не знаю, есть ли лучший способ, но один из способов достижения этого - написать небольшую схему-заглушку, которая импортирует оба, и предоставить эту заглушку в качестве свойства schemaSource.Процессор будет использовать любые объявления схемы, совпадающие с пространством имен элементов в исходном документе.

(Использование пространств имен для конкретной версии облегчает эту задачу - проверку правильности. Но облегчает последующую обработку XML, например, с использованием XPath, сложнее, потому что сложно написать код, который работает с обоими пространствами имен.)

...