1

I have an unusual request. I need to generate an xml file that looks for eg., something like below

<?xml version="1.0" encoding="UTF-8"?>
<pk:DeviceInfo xmlns:pk="urn:ietf:params:xml:ns:kyp:pk" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <pk:Manufacturer xmlns:pk="urn:ietf:params:xml:ns:kyp:pk" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      ABC
      </pk:Manufacturer>
      <pk:SerialNo>123456</pk:SerialNo>
      <pk:Model>Model1</pk:Model>
      <pk:IssueNo>1</pk:IssueNo>
</pk:DeviceInfo>

I am generating the xml using jdom api. The problem is, even if i declare namespace for pk:Manufacturer element, jdom doesn't add it there because it is already declared in the root element. But i need to repeat the namespace declaration in the child element as well, because i need to send this file to another server that requires the xml to be in this format.
I believe jdom doen't allow this, so i tried to create the xml first with jdom and update the xml with dom parser to include the namespace to the child element using elmt.setAttributeNS(), but unfortunately this doesn't seem to work. Has anybody faced this problem before?

4
  • 1
    "i need to send this file to another server that requires the xml to be in this format" suggests the other server does not understand XML with namespaces as clearly any namespaces declarations on an ancestor element are in scope for descendants unless overridden. Thus the inner namespace declarations are redundant and most serializers of DOM trees will not write them out. There is usually no easy way out other then fixing the other side to accept XML or to write your own serializer that ensures it write out redundant namespace declarations. Commented Nov 16, 2016 at 10:41
  • It is possible to implement your own customization of the XMLOutputter's "processor", and for that customization to print the namespace ar all relevant levels of the document. That would be a last resort, though. It would be better to fix the system on the other side to use an XML parser to parse the content (what you have now is obviously not a conforming parser). You will want to implement your own processor and change this line: github.com/hunterhacker/jdom/blob/master/core/src/java/org/… Commented Nov 16, 2016 at 11:39
  • You could try generating the XML using different namespace URIs at each level, and then do some post-processing (using non-XML tools) to replace the dummy URIs with the real ones. (But as others have said, if an application isn't reading or writing XML correctly, you really don't want to let its deficiencies permeate outwards to other parts of the system: you should fix the broken application). Commented Nov 16, 2016 at 12:15
  • Yes, its a bit wired that the target server expects redundant namespaces. I've already raised my concern regarding this, but i have no control over changing something at the server side. But luckily for me as @MartinHonnen suggested, LSSerializer is able to write the xml with redundant namespaces!. I was using javax.xml.transform.Transformer earlier, which apparently removed the redundants in the child elements. Commented Nov 17, 2016 at 3:33

1 Answer 1

2

You haven't shown us which DOM code you tried but when I test

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);

    DocumentBuilder db = dbf.newDocumentBuilder();

    Document doc = db.newDocument();

    String ns1 = "http://example.com/ns1";
    String ns2 = "http://example.com/ns2";

    Element root = doc.createElementNS(ns1, "pf1:root");
    root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:pf2", ns2);

    doc.appendChild(root);

    Element foo = doc.createElementNS(ns1, "pf1:foo");
    foo.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:pf1", ns1);
    foo.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:pf2", ns2);
    root.appendChild(foo);

    DOMImplementationLS  domImp = (DOMImplementationLS)doc.getImplementation();

    LSSerializer ser = domImp.createLSSerializer();

    System.out.println(ser.writeToString(doc));

with Oracle Java 1.8 the output is

<pf1:root xmlns:pf1="http://example.com/ns1" xmlns:pf2="http://example.com/ns2"><pf1:foo xmlns:pf1="http://example.com/ns1" xmlns:pf2="http://example.com/ns2"/></pf1:root>

thus the explicitly created namespace attribute declarations on the child are serialized. So that should be a way for the W3C DOM, explicitly create namespace declarations on the elements you need them and use LSSerializer to write out the tree.

Sign up to request clarification or add additional context in comments.

1 Comment

Perfect! LSSerializer did the trick for me. Earlier i was using javax.xml.transform.Transformer to convert the dom source to the xml. Now LSSerializer can write xml with repetitive namespaces.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.