问题
I've been trying to get XInclude working in my XML document and finally have it working in Oxygen XML, which I'm using to author the XML documents.
I then went to my app, written in Java, but it doesn't seem to support any form of XPointer resolution except using something like: element(/1/2).
This is, obviously, an awful scheme to have to use since every time the document is edited the XPointer needs changing to reflect the new position of the node in the XML!
The scheme I had working simply used xml:id in the target document:
<foo>
<bar xml:id="ABCD" />
</foo>
and then, in the other document:
<lorem>
<ipsum>
<xi:include href="target.xml" xpointer="ABCD" />
</ipsum>
</lorem>
Which I anticipate (and am getting in Oxygen) results in something like:
<lorem>
<ipsum>
<bar xml:id="ABCD" />
</ipsum>
</lorem>.
However, in Java it fails with:
Resource error reading file as XML (href='data/target.xml'). Reason: XPointer resolution unsuccessful.
If, however, I change the include tag to use
xpointer="element(/1/1)"
then it works very nicely - but, as I've said, that's a very poor solution.
I'm simply using the implementations that are included with the Java runtime (1.8).
Here's the code I'm using:
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:
According to Apache Xerces's docs on XInclude (which is used internally for XML parsing by Java)
for shorthand pointers and element() XPointers, currently only DTD-determined IDs are supported.
This means that you need to put markup declarations such as the following into your target.xml
file (telling the XML parser that the id
attribute is to be treated as attribute with ID
semantics, and telling XInclude to interpret "bare" XPointers as ID references):
<!DOCTYPE foo [
<!ATTLIST bar id ID #IMPLIED>
]>
<foo>
<bar id="ABCD"/>
</foo>
If you now use the following document as your source XML (which you've named result.xml
in your example code, and which I've edited to contain an XInclude namespace URI binding for xi
)
<lorem xmlns:xi="http://www.w3.org/2001/XInclude">
<ipsum>
<xi:include href="target.xml" xpointer="ABCD"/>
</ipsum>
</lorem>
then Xerces will build up a Document
where XInclude processing has been performed as desired (where i've put your example data into the target.xml
file in the same directory as the result.xml
file):
<lorem xmlns:xi="http://www.w3.org/2001/XInclude">
<ipsum>
<bar id="ABCD" xml:base="target.xml"/>
</ipsum>
</lorem>
The Java code I've used to produce the document is simplified from your example and doesn't contain third-party libs:
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();
}
}
Seeing as you also use XML Schema validation, I'd also like to point out the potential interaction of XInclude with XML Schema as eg. discussed in XInclude Schema/Namespace Validation?, and also a potential alternative discussed in Duplicate some parts of XML without rewriting them .
来源:https://stackoverflow.com/questions/50294372/trying-to-use-xinclude-with-java-and-resolving-the-fragment-with-xmlid