尝试将 XInclude 与 Java 一起使用并使用 xml:id 解析片段
Trying to use XInclude with Java and resolving the fragment with xml:id
我一直在尝试让 XInclude 在我的 XML 文档中工作,并最终让它在我用来创作 XML 文档的 Oxygen 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 中它失败了:
Resource error reading file as XML (href='data/target.xml'). Reason:
XPointer resolution unsuccessful.
但是,如果我将包含标记更改为使用
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()));
根据Apache Xerces's docs on XInclude(由Java内部用于XML解析)
for shorthand pointers and element() XPointers, currently only DTD-determined IDs are supported.
这意味着您需要将如下标记声明放入 target.xml
文件中(告诉 XML 解析器 id
属性将被视为属性ID
语义,并告诉 XInclude 将 "bare" 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 将构建一个 Document
,其中已根据需要执行 XInclude 处理(我已将您的示例数据放入与 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 Schema/Namespace Validation?, and also a potential alternative discussed in 中讨论。
我一直在尝试让 XInclude 在我的 XML 文档中工作,并最终让它在我用来创作 XML 文档的 Oxygen 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 中它失败了:
Resource error reading file as XML (href='data/target.xml'). Reason: XPointer resolution unsuccessful.
但是,如果我将包含标记更改为使用
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()));
根据Apache Xerces's docs on XInclude(由Java内部用于XML解析)
for shorthand pointers and element() XPointers, currently only DTD-determined IDs are supported.
这意味着您需要将如下标记声明放入 target.xml
文件中(告诉 XML 解析器 id
属性将被视为属性ID
语义,并告诉 XInclude 将 "bare" 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 将构建一个 Document
,其中已根据需要执行 XInclude 处理(我已将您的示例数据放入与 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 Schema/Namespace Validation?, and also a potential alternative discussed in