2

我一直在尝试让 XInclude 在我的 XML 文档中工作,最后让它在 Oxygen XML 中工作,我用它来创作 XML 文档。

然后我去了我的应用程序,它是用 Java 编写的,但它似乎不支持任何形式的 XPointer 分辨率,除非使用类似元素(/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()));
4

1 回答 1

3

根据Apache Xerces 在 XInclude 上的文档(Java 在内部用于 XML 解析)

对于速记指针和 element() XPointers,目前仅支持 DTD 确定的 ID。

这意味着您需要将如下标记声明放入您的target.xml文件中(告诉 XML 解析器该id属性将被视为具有ID语义的属性,并告诉 XInclude 将“裸”XPointers 解释为 ID 引用):

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

如果您现在使用以下文档作为源 XML(您已result.xml在示例代码中命名,并且我已对其进行编辑以包含 XInclude 命名空间 URI 绑定xi

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

然后 Xerces 将建立一个DocumentXInclude 处理已根据需要执行的位置(我已将您的示例数据放入与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 Schema 验证,我还想指出 XInclude 与 XML Schema 的潜在交互,例如。XInclude Schema/Namespace Validation? ,并且也是复制 XML 的某些部分而不重写它们的潜在替代方法。

于 2018-05-14T14:30:34.670 回答