Search code examples
javaxmlsaxstax

What's the right way to produce a XML content in Java?


I've read several questions and tutorials over the internet such as

But since this is the very first time I have to manipulate XML documents in Java I'm still a little bit confused. The XML content is written with String concatenation and that seems to me wrong. It is the same to concatenate Strings to produce a JSON object instead of using a JSONObject class. That's the way the code is written right now:

"<msg:restenv xmlns:msg=\"http://www.b2wdigital.com/umb/NEXM_processa_nf_xml_req\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.b2wdigital.com/umb/NEXM_processa_nf_xml_req req.xsd\"><autenticacao><usuario>"
            + usuario + "</usuario><senha>" + StringUtils.defaultIfBlank(UmbrellaRestClient.PARAMETROS_INFRA_UMBRELLA.get("SENHA_UMBRELLA"), "WS.INTEGRADOR")
            + "</senha></autenticacao><parametros><parametro><p_vl_gnre>" + valorGNRE + "</p_vl_gnre><p_cnpj_destinatario>" + cnpjFilial + "</p_cnpj_destinatario><p_num_ped_compra>" + idPedido
            + "</p_num_ped_compra><p_xml_sefaz><![CDATA[" + arquivoNfe + "]]></p_xml_sefaz></parametro></parametros></msg:restenv>"

In my research I think that almost everything I've read pointed to SAX as the best solution but I never really found something really useful to read about it, almost everything states that we have to create a handler and override startElement, endElement and characters methods.

I don't have to serialize the XML file in hard disk or database or anything else, I just need to pass its content to a webservice.

So my question really is, which is the right way to do it?

  • Concatenate Strings the way things are done right now?
  • Write the XML file using a Java API like Xerces? I have no clue on how that can be done.
  • Read the XML file with streams and just change node texts? My XML without the files would be like that:

    <msg:restenv xmlns:msg="{url}"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="{schemaLocation}">
        <autenticacao>
            <usuario></usuario>
            <senha></senha>
        </autenticacao>
        <parametros>
            <parametro>
                <p_vl_gnre></p_vl_gnre>
                <p_cnpj_destinatario></p_cnpj_destinatario>
                <p_num_ped_compra></p_num_ped_compra>
                <p_xml_sefaz><![CDATA[]]></p_xml_sefaz>
            </parametro>
        </parametros>
    </msg:restenv>
    
  • I've also read something about using Apache Velocity as a template Engine since I don't actually have to serialize the XML and that's a approach that I really like because I've already worked with this framework and it's a really simple framework.

Again, I'm not looking for the best way, but the right one with tutorials and examples, if possible, on how to get things done.


Solution

  • It all depends on context. There is no single "right way".

    The biggest issues with concatenation is the combination of escaping the XML in to a String constant (which is fiddly), but also escaping the values that you can using so that they're correct for an XML document.

    For small XMLs, that's fine.

    But for larger ones, it can be a pain.

    If most of your XML is boilerplate with just a few values inserted, you may find that templates using something like Velocity or any of the other several libraries may be quite effective. It helps keep the template "native" (you don't have to wrap it in "'s and escape it), plus it keeps the XML out of your code, but easily lets you stamp in the parts that you need to do.