Save new XML node to file
Asked Answered
K

2

4

I am trying to save nodeList node that contains XML as a new file, here is the Node list that get a new XML doc and split to smaller XMLs:

public void split(Document inDocument) throws ParserConfigurationException,
            SAXException, IOException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        SaveXML savePerJob = new SaveXML();
        // Load the input XML document, parse it and return an instance of the
        // Document class.
        Document document = inDocument;
        //all elements
        //jobs
        NodeList nodes = document.getDocumentElement().getChildNodes();
        NodeList jobs = nodes.item(7).getChildNodes();
        for(int j =0; j<jobs.getLength(); j++){
            Node itm = jobs.item(j);
            String itmName = itm.getFirstChild().getNodeName();
            String itmID = itm.getFirstChild().getTextContent();
            System.out.println("name: " + itmName + " value: " + itmID);
            //here I want to save the node as a new .xml file
        }
    }

the output is a long list like :

name: id value: 9496425

Now I want to save the node itm as new new .xml file and I didnt find the function that returns the node as is. Thanks.

Kuehn answered 26/11, 2015 at 10:6 Comment(1)
BTW - I want the result to include the XML tags.Kuehn
B
18

You can convert your node to a string and save this string into a .xml file.

Convert a node to string

The method below will turn a node into an xml string. It's a JDK only solution, no dependencies required.

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.StringWriter;

public static String toString(Node node, boolean omitXmlDeclaration, boolean prettyPrint) {
    if (node == null) {
        throw new IllegalArgumentException("node is null.");
    }

    try {
        // Remove unwanted whitespaces
        node.normalize();
        XPath xpath = XPathFactory.newInstance().newXPath();
        XPathExpression expr = xpath.compile("//text()[normalize-space()='']");
        NodeList nodeList = (NodeList)expr.evaluate(node, XPathConstants.NODESET);

        for (int i = 0; i < nodeList.getLength(); ++i) {
            Node nd = nodeList.item(i);
            nd.getParentNode().removeChild(nd);
        }

        // Create and setup transformer
        Transformer transformer =  TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        
        if (omitXmlDeclaration == true) {
           transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        }

        if (prettyPrint == true) {
           transformer.setOutputProperty(OutputKeys.INDENT, "yes");
           transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
        }

        // Turn the node into a string
        StringWriter writer = new StringWriter();
        transformer.transform(new DOMSource(node), new StreamResult(writer));
        return writer.toString();
    } catch (TransformerException e) {
        throw new RuntimeException(e);
    } catch (XPathExpressionException e) {
        throw new RuntimeException(e);
    }
}
Brig answered 26/11, 2015 at 10:30 Comment(7)
Yes but then it will be a string without the .xml tags I want.Kuehn
@ItsikMauyhas Please check the snippet I added to my answer.Brig
The String output will include the XML tags?Kuehn
'options.indent()' dont compile.Kuehn
@ItsikMauyhas Replace options.indent() with "4". See my update.Brig
@Stephan: I am getting "Namespace for prefix has not been declared" exception using this code. what is solution for it?Corneliacornelian
@Corneliacornelian Can you please post a new question detailing your issue? Don t forget to link back your new question to this answer.Brig
O
2

Here is one possibility:

void save(Node node, OutputStream stream) throws Exception {
    DOMImplementationLS ls = (DOMImplementationLS) node.getOwnerDocument().getImplementation();
    LSOutput out = ls.createLSOutput();
    out.setByteStream(stream);
    LSSerializer ser = ls.createLSSerializer();
    ser.write(node, out);
}

Perhaps you should make sure that node is really an Element, but I leave that as an excersize.

Opheliaophelie answered 26/11, 2015 at 10:37 Comment(2)
if node wasn't a element I couldn't return its IDKuehn
Perhaps, but you do not have any checks that you are dealing with an element. And in all, your code is very sensitive to format changes in the input document, but that's another story.Opheliaophelie

© 2022 - 2024 — McMap. All rights reserved.