XML для проверки по нескольким схемам xsd - PullRequest
4 голосов
/ 12 апреля 2010

Я пишу xsd и код для проверки, поэтому у меня есть большой контроль здесь.

Я хотел бы иметь средство загрузки, которое добавляет материал в мое приложение на основе XML-файла. Одна часть XML-файла должна быть проверена на соответствие различным схемам на основе одного из значений в другой его части. Вот пример для иллюстрации:

<foo>
  <name>Harold</name>
  <bar>Alpha</bar>
  <baz>Mercury</baz>
  <!-- ... more general info that applies to all foos ... -->

  <bar-config>
    <!-- the content here is specific to the bar named "Alpha" -->
  </bar-config>
  <baz-config>
    <!-- the content here is specific to the baz named "Mercury" -->
  </baz>
</foo>

В этом случае есть некоторый контролируемый словарь для содержания <bar>, и я могу справиться с этой частью очень хорошо. Затем, основываясь на значении bar, следует использовать соответствующую XML-схему для проверки содержимого bar-config. Аналогично для baz и baz-config.

Код, выполняющий анализ / проверку, написан на Java. Не уверен, насколько будет зависеть решение от языка.

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

Кроме того, возможные значения для <bar> и <baz> являются ортогональными, поэтому я не хочу делать это расширением для каждой возможной комбинации bar / baz. Я имею в виду, что если существует 24 возможных значения / схемы столбца и 8 возможных значений / схем baz, я хочу иметь возможность написать 1 + 24 + 8 = 33 суммарных схемы вместо 1 * 24 * 8 = 192 общих схем .

Кроме того, я бы предпочел НЕ разбивать bar-config и baz-config на отдельные xml-файлы, если это возможно. Я понимаю, что это может значительно облегчить все проблемы, поскольку каждый XML-файл будет иметь одну схему, но я пытаюсь выяснить, есть ли хорошее решение для одного XML-файла.

Ответы [ 4 ]

6 голосов
/ 28 апреля 2010

Я наконец-то понял это.

Прежде всего, в схеме foo элементы bar-config и baz-config имеют тип, который включает в себя элемент any, например:

<sequence>
    <any minOccurs="0" maxOccurs="1"
        processContents="lax" namespace="##any" />
</sequence>

Затем в xml необходимо указать правильное пространство имен, используя атрибут xmlns дочернего элемента bar-config или baz-config, например:

<bar-config>
    <config xmlns="http://www.example.org/bar/Alpha">
        ... config xml here ...
    </config>
</bar-config>

Тогдаваш файл XML-схемы для панели Alpha будет иметь целевое пространство имен http://www.example.org/bar/Alpha и определит корневой элемент config.

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

Пока что мы выполнили требование, чтобы автор xml мог написать xml таким образомчто он проверен в редакторе.

Теперь нам нужно, чтобы потребитель мог проверить.В моем случае я использую Java.

Если по какой-то случайности вы знаете файлы схемы, которые вам нужно будет использовать для предварительной проверки, то вы просто создаете один объект Schema и проверяете как обычновот так:

Schema schema = factory().newSchema(new Source[] {
    new StreamSource(stream("foo.xsd")),
    new StreamSource(stream("Alpha.xsd")),
    new StreamSource(stream("Mercury.xsd")),
});

В этом случае, однако, мы не знаем, какие файлы xsd использовать, пока не проанализируем основной документ.Итак, общая процедура такова:

  1. Проверка xml с использованием только основной (foo) схемы
  2. Определение схемы, используемой для проверки части документа
  3. Найдите узел, который является корнем части для проверки, используя отдельную схему
  4. Импортируйте этот узел в новый документ
  5. Проверьте новый документ, используя другой файл схемы

Предостережение: похоже, что документ должен быть построен с учетом пространства имен, чтобы это работало.

Вот некоторый код (он был разорван из разных местмой код, поэтому при копировании и вставке могут возникать ошибки:

// Contains the filename of the xml file
String filename;

// Load the xml data using a namespace-aware builder (the method 
// 'stream' simply opens an input stream on a file)
Document document;
DocumentBuilderFactory docBuilderFactory =
    DocumentBuilderFactory.newInstance();
docBuilderFactory.setNamespaceAware(true);
document = docBuilderFactory.newDocumentBuilder().parse(stream(filename));

// Create the schema factory
SchemaFactory sFactory = SchemaFactory.newInstance(
    XMLConstants.W3C_XML_SCHEMA_NS_URI);

// Load the main schema
Schema schema = sFactory.newSchema(
    new StreamSource(stream("foo.xsd")));

// Validate using main schema
schema.newValidator().validate(new DOMSource(document));

// Get the node that is the root for the portion you want to validate
// using another schema
Node node= getSpecialNode(document);

// Build a Document from that node
Document subDocument = docBuilderFactory.newDocumentBuilder().newDocument();
subDocument.appendChild(subDocument.importNode(node, true));

// Determine the schema to use using your own logic
Schema subSchema = parseAndDetermineSchema(document);

// Validate using other schema
subSchema.newValidator().validate(new DOMSource(subDocument));
2 голосов
/ 13 апреля 2010

Взгляните на NVDL (язык диспетчера проверки на основе пространства имен) - http://www.nvdl.org/

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

Здесь есть учебник - http://www.dpawson.co.uk/nvdl/ - и реализация Java здесь - http://jnvdl.sourceforge.net/

Надеюсь, это поможет! Kevin

0 голосов
/ 06 февраля 2019

Вы также можете использовать «распознаватель ресурсов», чтобы позволить «авторам xml» указать свой собственный файл схемы, по крайней мере, до некоторой степени, например: https://stackoverflow.com/a/41225329/32453 в конце дня, вы хотите полностью совместимый XML-файл, который в любом случае можно проверить с помощью обычных инструментов:)

0 голосов
/ 13 апреля 2010

Вам необходимо определить целевое пространство имен для каждой отдельно проверенной части экземпляра документа. Затем вы определяете мастер-схему , которая использует <xsd:include> для ссылки на документы схемы для этих компонентов.

Ограничением этого подхода является то, что вы не можете позволить отдельным компонентам определять схемы, которые должны использоваться для их проверки. Но в целом плохая идея - разрешать документу указывать, как его проверять (т. Е. Валидация должна выполняться под контролем вашего приложения).

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