Попытка использовать XInclude с Java и разрешение фрагмента с помощью xml: id - PullRequest
0 голосов
/ 11 мая 2018

Я пытался заставить XInclude работать в моем XML-документе и, наконец, заставить его работать в Oxygen XML, который я использую для создания XML-документов.

Затем я пошел в свое приложение, написавв Java, но, похоже, он не поддерживает какую-либо форму разрешения XPointer, кроме использования чего-то вроде: element (/ 1/2).

Это, очевидно, ужасная схема, которую приходится использовать каждый раз, когдадокумент отредактирован, так как XPointer необходимо изменить, чтобы отразить новую позицию узла в XML!

Схема, с которой я работал, просто использовала xml: id в целевом документе:

<foo>
    <bar xml:id="ABCD" />
</foo>

и затем, в другом документе:

<lorem>
    <ipsum>
         <xi:include href="target.xml" xpointer="ABCD" />
    </ipsum>
</lorem>

То, что я ожидаю (и получаю в кислороде), приводит к чему-то вроде:

<lorem>
    <ipsum>
         <bar xml:id="ABCD" />
    </ipsum>
</lorem>.

Однако в Java это терпит неудачу с:

Ошибка чтения файла в формате XML (href = 'data / target.xml').Причина: разрешение XPointer не удалось.

Если, однако, я изменю тег включения для использования

xpointer="element(/1/1)"

, тогда он будет работать очень хорошо - но, как я уже сказал, этоочень плохое решение.

Я просто использую реализации, включенные в среду выполнения Java (1.8).

Вот код, который я использую:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setXIncludeAware(true);
Source resultSource = new 
StreamSource(Gdx.files.internal("data/result.xsd").read());
            Source targetSource = new 
StreamSource(Gdx.files.internal("data/target.xsd").read());
            Source[] schemaFiles = {targetSource, resultSource};
            schema = 
SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema")
                    .newSchema(schemaFiles);
            factory.setSchema(schema);
            builder = factory.newDocumentBuilder();
            itemDoc = builder.parse(new 
InputSource(Gdx.files.internal("data/result.xml").read()));

1 Ответ

0 голосов
/ 14 мая 2018

В соответствии с Документами Apache Xerces для XInclude (который используется внутренне для синтаксического анализа XML в Java)

для кратких указателей и XPointers элемента (), в настоящее время только DTD-определенныхПоддерживаются идентификаторы.

Это означает, что вам нужно поместить объявления разметки, такие как следующие, в ваш файл target.xml (сообщающий анализатору XML, что атрибут id должен рассматриваться как атрибут сID семантика и указание XInclude интерпретировать «голые» XPointers как ссылки на идентификаторы):

<!DOCTYPE foo [
  <!ATTLIST bar id ID #IMPLIED>
]>
<foo>
    <bar id="ABCD"/>
</foo>

Если вы сейчас используете следующий документ в качестве исходного XML (который вы назвали result.xml в своемпример кода, и который я отредактировал, чтобы он содержал привязку URI пространства имен XInclude для xi)

<lorem xmlns:xi="http://www.w3.org/2001/XInclude">
  <ipsum>
    <xi:include href="target.xml" xpointer="ABCD"/>
  </ipsum>
</lorem>

, тогда Xerces создаст Document, где обработка XInclude была выполнена по желанию (где япоместил данные вашего примера в файл target.xml в том же каталоге, что и файл result.xml):

<lorem xmlns:xi="http://www.w3.org/2001/XInclude">
  <ipsum>
    <bar id="ABCD" xml:base="target.xml"/>
  </ipsum>
</lorem>

Java-код, который я использовал для создания документа:упрощен из вашего примера и не содержит сторонних библиотек:

import java.io.*;
import javax.xml.*;
import javax.xml.parsers.*;
import javax.xml.validation.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
import org.w3c.dom.*;

public class t {

  public static void main(String[] args) {
    try {
      DocumentBuilderFactory factory =
        DocumentBuilderFactory.newInstance();
      factory.setNamespaceAware(true);
      factory.setXIncludeAware(true);
      DocumentBuilder builder = factory.newDocumentBuilder();
      Document itemDoc = builder.parse(new File("result.xml"));
      System.out.println(serialize(itemDoc));
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
  }

  static String serialize(Document doc) throws Exception {
    Transformer transformer =
      TransformerFactory.newInstance().newTransformer();
    StreamResult result = new StreamResult(new StringWriter());
    DOMSource source = new DOMSource(doc);
    transformer.transform(source, result);
    return result.getWriter().toString();
  }
}

Поскольку вы также используете проверку XML-схемы, я также хотел бы указать на потенциальное взаимодействие XInclude с XML-схемой, например:,обсуждается в Проверка схемы / пространства имен XInclude? , а также потенциальная альтернатива, обсуждаемая в Дублируйте некоторые части XML, не переписывая их .

...