adding namespace and namespace prefix using dom4j

2019-08-01 06:33发布

问题:

i am updating one xml using dom4j as below.

    SAXReader reader = new SAXReader();
document = reader.read( xmlFileName );

but it removes all namespaces from the elements so wanna add manually but it does not work when i tried the following code.

    Element e1 = root.addElement("jmsProducer");   
    e1.addNamespace("AEService", "http://www.tibco.com/xmlns/aemeta/services/2002");

my xml looks like

    <AEService:jmsProducer objectType="endpoint.JMSPublisher" name="Pub1EndPoint">  
    <AEService:wireFormat>aeXml</AEService:wireFormat>

which sud look like

    <AEService:jmsProducer xmlns:AEService="http://www.tibco.com/xmlns/aemeta/services   /2002" objectType="endpoint.JMSPublisher" name="Pub1EndPoint">
    <AEService:wireFormat>aeXml</AEService:wireFormat>

any help is highly appriciated. banging on this for two days tried using documentfactory method still no use.

回答1:

I realize that this is an old thread, and dom4j may not have had adequate namespace capabilities at the time the answers were written, but it looks like dom4j is now able to accomplish this quite easily with the version I am using (1.6.1). I came here looking for help on how to build a namespace aware XML with dom4j, posting my Java code (to build the XML snippet in the original post) in case it helps someone.

Here is the Java code to build it.

Document xmldoc = DocumentHelper.createDocument();
Namespace aeServiceNs = new Namespace("AEService",
  "http://www.tibco.com/xmlns/aemeta/services/2002");
Element root = xmldoc.addElement(new QName("jmsProducer", aeServiceNs))
                     .addAttribute("objectType", "endpoint.JMSPublisher")
                     .addAttribute("name", "Pub1EndPoint");
Element wireformat = root.addElement(new QName("wireFormat", aeServiceNs))
                         .setText("aeXml");
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
XMLWriter xmlwriter = new XMLWriter(System.out, outputFormat);
xmlwriter.write(xmldoc);

produces this output:

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

<AEService:jmsProducer 
    xmlns:AEService="http://www.tibco.com/xmlns/aemeta/services/2002" 
    objectType="endpoint.JMSPublisher" name="Pub1EndPoint">
  <AEService:wireFormat>aeXml</AEService:wireFormat>
</AEService:jmsProducer>

Hope this helps.



回答2:

I suggest you dump dom4j and use JAXB or StAX. If you can't do that then try the below (I didn't verify this so post follow up questions as comments)

Namespace ns = new Namespace("AEService","http://www.tibco.com/xmlns/aemeta/services/2002")
document.add(ns);


回答3:

I found that in order for the namespace to be correctly set it needed to be recursively set on the entire hierarchy of nodes.

these two methods do the trick:

   /**
    * Recursively sets the namespace of the element and all its children.
    */
   private void setNamespaces( Element elem, Namespace ns ) {
      setNamespace( elem, ns );
      setNamespaces( elem.content(), ns );
   }

   /**
    * Recursively sets the namespace of the List and all children if the
    * current namespace is match
    */
   private void setNamespaces( List l, Namespace ns ) {
      Node n = null;
      for ( int i = 0; i < l.size(); i++ ) {
         n = ( Node ) l.get( i );

         if ( n.getNodeType() == Node.ATTRIBUTE_NODE ) {
            (( Attribute ) n).setNamespace( ns );
         }
         if ( n.getNodeType() == Node.ELEMENT_NODE ) {
            setNamespaces( ( Element ) n, ns );
         }
      }
   }

then I am able to add the namespace like so:

setNamespaces( ( Element ) xml.selectSingleNode( "/root/settings" ),
                  new Namespace( "", "http://www.penvision.se/printprocessor" ) );

Hope this helps



回答4:

I am able to add a namespace at the child element instead of the root element with the below steps:

  1. find the Node using xpath from created document.

  2. create name space prefix name and value.

  3. Add as element into node as below:

    Document document = DocumentHelper.createDocument();
    Element documentRoot = null;
    
    Element created = null;
    
    Node parentNode = null;
    documentRoot = DocumentHelper.createElement();
    parentNode = documentRoot.selectSingleNode("parentXPath");
    Namespace ns = new Namespace("name","value");
    created = ((Element) parentNode).addElement(new QName("elementName",ns1));
    


回答5:

Using the library dom4j:2.1.1

After initializing the document:

SAXReader reader = new SAXReader();
reader.getDocumentFactory().setXPathNamespaceURIs(ImmutableMap.of("x", "DAV:"));
Document doc = reader.read(new StringReader(xmlContent));
doc.getRootElement().selectNodes("//x:response")

I can prefix with the namespace x: the XPath expression.

Note: an empty namespace is not allowed. You need to specify a prefix.