2016-08-06 29 views
3

ich eine XML-Datei, die die folgenden hat:Java XML-Parsing - die Ausgabe von xi verschmelzenden: include

<contexts> 
    <context name="a"> 
     <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="reuse.xml"/> 
     <other_stuff/> 
    </context> 
    <context name="b"> 
     <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="reuse.xml"/> 
     <other_stuff/> 
    </context> 
</contexts> 

... und die reuse.xml durch die XInclude, über dem so etwas wie dieses enthält verwiesen:

<good_stuff/><!-- and a bunch of complex stuff -> 

ich versuche, einige Java-Code zu schreiben, die eine Schnur Ausgang für jeden Kontext Element erzeugen kann (leicht), aber statt der xi: Zeile enthalten, ersetzen, die mit dem Inhalt der Datei enthalten also geben Sie mir ein 'explodierter' String für jeden Kontext wie diesen:

<context name="a"> 
    <good_stuff/><!-- and a bunch of complex stuff -> 
    <other_stuff/> 
</context> 

Eher als das, was ich bekomme jetzt:

<context name="a"> 
    <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="reuse.xml"/> 
    <other_stuff/> 
</context> 

Hoffentlich habe ich erkläre mich klar, dass ich das xi nicht will: Text in meiner Ausgabe enthalten, sondern der Inhalt der andere Datei sollte durch ersetzt werden.

Ich gründe der Parser XInclude zu sein und bewusst Namensraum:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
factory.setNamespaceAware(true); 
factory.setXIncludeAware(true); 

...

dann die untergeordneten Knoten des Typs immer ich will (Typ gibt mir den Kontext, in diesem Fall).

NodeList result = doc.getElementsByTagName(type).item(0).getChildNodes(); 

Aber wenn ich über diese laufen und jedes Element auf den String mit folgendem passieren, wird die xi nicht ersetzen: include;

StringWriter sw = new StringWriter(); 
Transformer serializer = TransformerFactory.newInstance().newTransformer(); 
serializer.setOutputProperty(OutputKeys.INDENT, "no"); 
serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 
serializer.setOutputProperty(OutputKeys.STANDALONE, "yes"); 
serializer.transform(new DOMSource(element), new StreamResult(sw)); 
String result = sw.toString(); 

Gibt es eine Möglichkeit, dies mit dem JDK 8.7 integrierten XML-Parser zu tun, andere als String-Manipulation das xi zu ersetzen: include du?

Vielen Dank für Ihre Hilfe!

+0

ich das xi ersetzen würde: include mich, aber ich habe nicht die Notwendigkeit für String-Manipulation sehen. Allerdings könnte eine xi: include-Funktion zur Verfügung gestellt werden, ich weiß es nicht. – LarsH

+1

Ich würde vermuten, dass es ein Namespace-Problem ist, der W3C XInclude-Namespace ist "http: // www.w3.org/2001/XInclude" und nicht "http: // www.w3.org/2003/XInclude". –

Antwort

2

Ich glaube, Sie haben den falschen Namensraum für die XInclude Referenz verwendet, wenn ich die XML ändern

<?xml version="1.0" encoding="UTF-8"?> 
<contexts> 
    <context name="a"> 
     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="reuse.xml"/> 
     <other_stuff/> 
    </context> 
    <context name="b"> 
     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="reuse.xml"/> 
     <other_stuff/> 
    </context> 
</contexts> 

zu verwenden, die den Namespace http://www.w3.org/2001/XInclude im W3C XInclude spec https://www.w3.org/TR/xinclude/#syntax definiert verwendet und eine Probe XML-Dokument verwenden

<?xml version="1.0" encoding="UTF-8"?> 
<good_stuff/> 

dann die Java-Code-Ausgänge z

<context name="a"> 
     <good_stuff xml:base="reuse.xml"/> 
     <other_stuff/> 
    </context> 
<context name="b"> 
     <good_stuff xml:base="reuse.xml"/> 
     <other_stuff/> 
    </context> 

, wenn einen Standard-Transformator zur Ausgabe unter Verwendung der context Elemente:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    factory.setNamespaceAware(true); 
    factory.setXIncludeAware(true); 

    DocumentBuilder docBuilder = factory.newDocumentBuilder(); 

    Document doc = docBuilder.parse("file1.xml"); 

    NodeList contextElements = doc.getElementsByTagName("context"); 

    for (int i = 0, l = contextElements.getLength(); i < l; i++) { 
     Node element = contextElements.item(i); 
     StringWriter sw = new StringWriter(); 
     Transformer serializer = TransformerFactory.newInstance().newTransformer(); 
     serializer.setOutputProperty(OutputKeys.INDENT, "no"); 
     serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 
     serializer.setOutputProperty(OutputKeys.STANDALONE, "yes"); 

     serializer.transform(new DOMSource(element), new StreamResult(sw)); 
     String result = sw.toString(); 
     System.out.println(result); 
    } 
+0

Danke für die Vorschläge. Leider ist das Ändern der XML nicht in meiner Kontrolle, aber vielleicht kann ich eine schnelle Suche ändern und von 2003 bis 2001 ersetzen, bevor ich parse.Vorerst ging ich mit der Option, beide Dokumente zu analysieren und den Knoten zu übernehmen und ihn mit einer tiefen Kopie zu klonen, wann immer ich ein xi: include mit dem href als Ersatz finde. Danke allen! – loizos

+0

Sie sollten dem Anbieter des XML mitteilen, dass der Namespace ungültig ist. Vor einigen Jahren gab es einige Verwirrung über den XInclude-Namespace-URI. Zuerst wurde es als "http: // www.w3.org/2001/XInclude" definiert. Dann wurde es in "http: // www.w3.org/2003/XInclude" geändert und etwas später wieder zurück zu "http: // www.w3.org/2001/XInclude". Siehe https://www.w3.org/TR/2004/CR-xinclude-20040413/. – mzjn