2014-10-09 3 views
0

У меня возникают трудности при попытке проверить несколько файлов XML на несколько документов схемы с помощью Saxon. Трудности вызваны взаимозаменяемыми отношениями между несколькими элементами. Вот простая реконструкция проблемы.Проверка нескольких XML-файлов с помощью Saxon не выполняется, если элементы substitutionGroup добавляются в схему после проверки первого файла.

Схемы являются:

family.xsd

<?xml version="1.0" encoding="UTF-8"?> 
<schema targetNamespace="http://myexample/family" xmlns:fam="http://myexample/family" xmlns="http://www.w3.org/2001/XMLSchema"> 
    <element name="FamilyMember" type="string" /> 
    <element name="Parent" type="string" substitutionGroup="fam:FamilyMember"/> 
    <element name="Child" type="string" substitutionGroup="fam:FamilyMember"/> 
    <element name="Family"> 
    <complexType> 
     <sequence> 
     <element ref="fam:FamilyMember" maxOccurs="unbounded"/> 
     </sequence> 
    </complexType> 
    </element> 
</schema> 

family_ext.xsd

<?xml version="1.0" encoding="UTF-8"?> 
<schema targetNamespace="http://myexample/family_ext" xmlns:fam="http://myexample/family" xmlns="http://www.w3.org/2001/XMLSchema"> 
    <import namespace="http://myexample/family" schemaLocation="http://www.valid.nl/taxo3/family.xsd"/> 
    <element name="Cousin" type="string" substitutionGroup="fam:FamilyMember"/> 
</schema> 

два экземпляра документов:

family1.xml

<Family xmlns="http://myexample/family"> 
    <Parent>John</Parent> 
    <Child>Alice</Child> 
</Family> 

family2.xml

<Family xmlns="http://myexample/family" xmlns:fam2="http://myexample/family_ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://myexample/family_ext http://www.valid.nl/taxo3/family_ext.xsd" > 
    <Parent>John</Parent> 
    <Child>Alice</Child> 
    <fam2:Cousin>Pete</fam2:Cousin> 
</Family> 

Вот проблема: я сначала загрузить family.xsd в конфигурацию Saxon с использованием метода addSchemaSource. Затем я проверяю family1.xml. Это работает. Если я затем попытаться проверить family2.xml, я получаю следующее сообщение об ошибке:

In content of element <Family>: The content model does not allow element <Q{.../family_ext}Cousin> to appear immediately after element <{http://myexample/family}Child>. Expected <Q{.../family}FamilyMember> or nothing. 

Однако, если я первый проверки family2.xml, проверка завершается успешно (и если я затем проверить family1.xml это также успешно).

Обходной путь, который я нашел для этой проблемы, - очистить кеш схемы между валидациями. Однако это, в конечном счете, не очень удовлетворительное решение, потому что в фактическом прецеденте у меня есть кеш с десятками схем и, скорее, не нужно будет перезагружать их. Более того, когда я начинаю проверку, я еще не знаю, какой будет общий набор shemas, поэтому я не могу упреждающе загружать их все (в контексте вышеприведенного примера я не могу загрузить как family.xsd, так и family_ext.xsd в начале проверки).

Почему заказ, в котором я выполняю валидации, важен? И есть ли способ заставить Саксон обрабатывать эти виды валидации без необходимости очищать кеш схемы?

ответ

0

Saxon должен сообщить вам об ошибке при загрузке второго документа схемы, указав, что вы не можете добавлять членов в группу замещения, которая уже использовалась для проверки. Причина этого в том, что изменение схемы делает недействительными предыдущие результаты. В контексте XSLT/XQuery это актуально, поскольку первый документ все еще может быть вокруг, и его аннотации типа (полученные от обработки схемы) могут повлиять на способ его обработки; если типы схем, которые использовались во время проверки достоверности, существенно отличаются от типов схем, используемых во время запроса/преобразования, тогда всевозможные вещи могут пойти не так. Таким образом, ответ на ваш вопрос заключается в том, что вы должны загружать все ваши документы схемы в саксонскую конфигурацию перед использованием (собранной) схемы. На самом деле правила не столь строги, как есть, есть много изменений, которые вы можете сделать безопасно. Изменения, которые Saxon проверяет и пытается предотвратить, добавляют к членству в группе подстановок и добавляют новые типы, полученные расширением из существующих типов. Существуют и другие небезопасные изменения, которые, по-видимому, необходимо проверить Saxon: например, если вы добавите новое объявление глобального элемента с именем X, это может привести к аннулированию содержимого, содержащего элемент X, если он был слабо проверен.

Я не знаю, почему Саксон не сообщает об ошибке при добавлении в группу замещения. Я исследую это.

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

Позже: я пытался воспроизвести это следующим образом:

  Processor proc = new Processor(true); 
      SchemaManager sm = proc.getSchemaManager(); 
      sm.load(new StreamSource(new StringReader(sch1))); 
      System.err.println("Schema 1 OK"); 
      sm.newSchemaValidator().validate(new StreamSource(new StringReader(doc1))); 
      System.err.println("Doc 1 OK"); 
      sm.load(new StreamSource(new StringReader(sch2))); 
      System.err.println("Schema 2 OK"); 
      sm.newSchemaValidator().validate(new StreamSource(new StringReader(doc2))); 
      System.err.println("Doc 2 OK"); 

где SCH1, SCH2, doc1 и doc2 ваши примеры документов и схем. Я получаю то, что и следовало ожидать, на погрузочной SCH2:

net.sf.saxon.s9api.SaxonApiException: It is not possible to add to the 
substitution group of element FamilyMember in namespace 'http://myexample/family', 
because the schema for that namespace has already been used for validating instance 
documents, or for compiling queries or stylesheets 
+0

Примечание, проблема регистрируется здесь: https://saxonica.plan.io/issues/2174 –

+0

Мы обнаружили, что такое поведение Saxon фактически описана в класс SchemaManager [.NET api] (http://www.saxonica.com/documentation9.4-demo/dotnetdoc/Saxon/Api/SchemaManager.html) (позорно это не присутствует в java-документе!). Причина, по которой я не получал исключение, которое вы ожидали, состоит в том, что я явно не загружал схему family_ext в конфигурацию, но вместо этого Saxon обнаружил ее через подсказку schemaLocation. Если я явно загружу схему, я действительно получаю исключение, которое вы упомянули. –

+0

OK. Если вы полагаетесь на подсказку расположения схемы, она будет проигнорирована на том основании, что схема для требуемого пространства имен уже доступна. У меня создалось впечатление, что опция MULTIPLE_SCHEMA_IMPORTS заставит ее загружаться в любом случае, но это не так. –