XML XInclude теряет пространство имен во включенных узлах

Я пытаюсь использовать пространства имен в файле xml, состоящем из нескольких файлов.

XML-схема

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema
    version="1.0"
    attributeFormDefault="unqualified"
    elementFormDefault="qualified"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="urn:mynamespace"
    targetNamespace="urn:mynamespace">

    <xsd:element name="main_element" type="typeMainElement" />

    <xsd:complexType name="typeMainElement">
        <xsd:sequence>
            <xsd:element name="inner_element" type="typeInnerElement" />
        </xsd:sequence>
    <xsd:attribute name="test_attribute" type="xsd:string" use="required" />
    </xsd:complexType>

    <xsd:complexType name="typeInnerElement">
        <xsd:sequence>
            <xsd:element name="description" type="xsd:string" minOccurs="0" />
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

Основной XML

<main_element test_attribute="value"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns="urn:mynamespace">
    <inner_element>
        <description>Test</description>
    </inner_element>
</main_element>

Проверка XML с помощью XML-схемы работает отлично. Но если я попытаюсь передать какую-то часть XML на аутсорсинг, полагаясь на XInclude, то ничего больше не будет работать.

Разделенный XML

<main_element test_attribute="value"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns="urn:mynamespace">
    <xi:include href="simple_part.xml" />
</main_element>

Включенный XML

<inner_element>
    <description>Test</description>
</inner_element>

Попытка проверить Разделенный XML возвращает ошибку:

simple_part.xml:1: элемент inner_element: ошибка достоверности схемы: элемент 'inner_element': этот элемент не ожидается. Ожидается ({urn:mynamespace}inner_element).

simple_main_element.xml не проходит проверку

Кажется, что при включении я теряю наследование пространства имен, поэтому включенный контент больше не имеет пространства имен.

-- Как решить эту проблему, не добавляя везде префиксы пространств имен? --

-- ДОБАВЛЕН ВОПРОС: как решить проблему еще и в том случае, когда включение происходит из другого каталога, например <xi:include href="subdir/simple_part.xml" />?


person Kamafeather    schedule 12.03.2015    source источник


Ответы (1)


Что ж, похоже, вам нужно выполнить несколько модификаций:

1) В вашем XML-фрагменте вам необходимо объявить то же пространство имен, что и в «основном» документе.

 <inner_element xmlns="urn:mynamespace">
   <description>Test</description>
 </inner_element>

2) В итоговом документе автоматически устанавливается атрибут xml:base (см. спецификацию XInclude, §4.5.5 и C .1), поэтому вам нужно объявить его в своей схеме, объявив этот атрибут и импортировав пространство имен xml следующим образом:

   <xsd:schema
       version="1.0"
       attributeFormDefault="unqualified"
       elementFormDefault="qualified"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns="urn:mynamespace"
       targetNamespace="urn:mynamespace">

       <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/03/xml.xsd" />

       <xsd:element name="main_element" type="typeMainElement" />

       <xsd:complexType name="typeMainElement">
           <xsd:sequence>
               <xsd:element name="inner_element" type="typeInnerElement" />
           </xsd:sequence>
       <xsd:attribute name="test_attribute" type="xsd:string" use="required" />
       </xsd:complexType>

       <xsd:complexType name="typeInnerElement">
           <xsd:sequence>
               <xsd:element name="description" type="xsd:string" minOccurs="0" />
           </xsd:sequence>
           <xsd:attribute ref="xml:base"/>
       </xsd:complexType>
   </xsd:schema>

Альтернативное решение с сущностями

Вам нужно объявить (проанализированные) объекты в DOCTYPE в начале «главного» документа и использовать ссылку вместо <xi:include> следующим образом:

<?xml version="1.0"?>
<!DOCTYPE main_element [
  <!ENTITY simple_part SYSTEM "simple_part.xml">
]>
<main_element test_attribute="value"
     xmlns:xi="http://www.w3.org/2001/XInclude"
     xmlns="urn:mynamespace">
   <!-- call a reference instead of xi:include -->
   &simple_part_1;
</main_element>

Simple_part.xml будет именно тем, что вам нужно в исходном сообщении:

<inner_element>
  <description>Test</description>
</inner_element>
person potame    schedule 12.03.2015
comment
@Kamafeather Если этот ответ решит вашу проблему, примите его. - person potame; 13.03.2015
comment
Да, это так. Я уже смог решить эту проблему, действительно добавив пространство имен. Решение нормальное, но я хочу избежать дополнительного атрибута xml:base в схеме (на мой взгляд, это не что-то связанное с определением даты, а просто обходной путь, который добавляет грязи [я не виню вас, я знаю, что это общее решение ;) ]). В любом случае, я добавил вопрос относительно URI включения, если вы хотите расширить свой ответ. - person Kamafeather; 13.03.2015
comment
@Kamafeather Мне просто пришло в голову: если вы не хотите изменять свою схему, возможно, вы можете использовать старую добрую ссылку на сущность? - person potame; 14.03.2015
comment
Я не понял, что может сделать для меня ссылка на сущность -_-' - person Kamafeather; 18.03.2015
comment
@Kamafeather Я добавил решение сущности в свой ответ. - person potame; 18.03.2015
comment
О, спасибо, теперь понял. Даже если это не подходит для моего случая (я решил просто вручную удалить атрибут xml:base, потому что в моем контексте он не нужен). Но в любом случае полезно знать! - person Kamafeather; 18.03.2015