Home > Back-end >  Modify Xml File In Java
Modify Xml File In Java

Time:12-29

I'm new to xml parsing, I just need to modify the content of an xml response

Current xml bloc

  <app:control xmlns:vaext="http://www.vizrt.com/atom-ext">
        <app:draft>no</app:draft>
        <vaext:state name="published" href="http://test.com/escenic/content/state/workflow/online_staging/published?role=journalist&amp;role=editor&amp;role=administrator&amp;role=useradmin&amp;role=reader&amp;role=editeur_n1&amp;role=publicite"></vaext:state>
    </app:control>
I wanted to change it to :
<app:control xmlns:vaext="http://www.vizrt.com/atom-ext">
    <app:draft>no</app:draft>
    <vaext:state name="ready" href="http://test.comt/content/state/workflow/online_staging/published?role=editor">un-publish</vaext:state>
</app:control>

Currently, I can change the attributes "name" and "href" but the problem with the second part ( adding un-publish</vaext:state> )

          InputSource src = new InputSource(new StringReader(xmlString));
            Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(src);
            Node state = document.getElementsByTagName("state").item(0);
            Node currentstate = state.getAttributes().getNamedItem("name");
            currentstate.setTextContent("ready");
            Node href = state.getAttributes().getNamedItem("href");
                        href.setTextContent( "the new link");

CodePudding user response:

Do the transformation in XSLT:

<xsl:stylesheet version="3.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:vaext="http://www.vizrt.com/atom-ext">
  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="vaext:state">
    <vaext:state 
      href="http://test.comt/content/state/workflow/online_staging/published?role=editor" 
      name="ready">un-publish</vaext:state>   
  </xsl:template>
   
</xsl:stylesheet>

and invoke it from Java:

Processor proc = new Processor(false);
Xslt30Transformer trans = proc.newXsltCompiler.compile(stylesheet).load30();
trans.transform(
    new StreamSource(new File(input)), 
    proc.newSerializer(new File(output));

I've shown this using XSLT 3.0 and the Saxon API (disclaimer: my company's product) to save a few lines of code, but this one is well within the capabilities of the XSLT 1.0 processor that comes built in to the JDK.

CodePudding user response:

It can assign by setTextContent() of Node of DOM in org.w3c.dom.Node

node.setTextContent("un-publish");

Demo Code as Modify.java file.

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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.transform.stream.StreamSource;
import java.io.*;

public class Modify {
    private static final String FILENAME = "./before.xml";
    private static final String FORMAT_XSLT = "./before-format.xslt";

    public static void main(String[] args) {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        try (InputStream is = new FileInputStream(FILENAME)) {
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(is);
            System.out.println("-------------- Before ----------------");
            writeXml(doc, System.out);

            NodeList listOfState = doc.getElementsByTagName("vaext:state");
            Node state = listOfState.item(0);
            if (state.getNodeType() == Node.ELEMENT_NODE) {
                String name = state.getAttributes().getNamedItem("name").getTextContent();
                if ("published".equals(name.trim())) {
                    state.getAttributes().getNamedItem("name").setTextContent("ready");
                    state.setTextContent("un-publish");
                }
                String href = state.getAttributes().getNamedItem("href").getTextContent();
                // http://test.com/escenic/content/state/workflow/online_staging/published?role=journalist&role=editor&role=administrator&role=useradmin&role=reader&role=editeur_n1&role=publicite
                // System.out.println(href);
                String target = "http://test.comt/content/state/workflow/online_staging/published?role=editor";
                state.getAttributes().getNamedItem("href").setTextContent(target);
            }
            // output to console
            System.out.println("-------------- After ----------------");
            writeXml(doc, System.out);
        } catch (ParserConfigurationException | SAXException
                | IOException | TransformerException e) {
            e.printStackTrace();
        }
    }

    // write doc to output stream
    private static void writeXml(Document doc,
            OutputStream output)
            throws TransformerException, UnsupportedEncodingException {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        // The default add many empty new line, not sure why?
        // https://stackoverflow.com/questions/58478632/how-to-avoid-extra-blank-lines-in-xml-generation-with-java
        // https://mkyong.com/java/pretty-print-xml-with-java-dom-and-xslt/
        // Transformer transformer = transformerFactory.newTransformer();
        // add a xslt to remove the extra newlines
        Transformer transformer = transformerFactory.newTransformer(
                new StreamSource(new File(FORMAT_XSLT)));
        // pretty print
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.STANDALONE, "no");

        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(output);
        transformer.transform(source, result);
    }
}

Input XML as before.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:app="http://www.w3.org/TR/html4/">
    <app:control xmlns:vaext="http://www.vizrt.com/atom-ext">
        <app:draft>no</app:draft>
        <vaext:state name="published" href="http://test.com/escenic/content/state/workflow/online_staging/published?role=journalist&amp;role=editor&amp;role=administrator&amp;role=useradmin&amp;role=reader&amp;role=editeur_n1&amp;role=publicite"></vaext:state>
    </app:control>
</xs:schema>

XSLT file as before-format.xslt name.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" cdata-section-elements="address bio"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Compile & Run it

$ javac Modify.java
$ java Modify
-------------- Before ----------------
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:app="http://www.w3.org/TR/html4/">
    <app:control xmlns:vaext="http://www.vizrt.com/atom-ext">
        <app:draft>no</app:draft>
        <vaext:state href="http://test.com/escenic/content/state/workflow/online_staging/published?role=journalist&amp;role=editor&amp;role=administrator&amp;role=useradmin&amp;role=reader&amp;role=editeur_n1&amp;role=publicite" name="published"/>
    </app:control>
</xs:schema>
-------------- After ----------------
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:app="http://www.w3.org/TR/html4/">
    <app:control xmlns:vaext="http://www.vizrt.com/atom-ext">
        <app:draft>no</app:draft>
        <vaext:state href="http://test.comt/content/state/workflow/online_staging/published?role=editor" name="ready">un-publish</vaext:state>
    </app:control>
</xs:schema>
  • Related