Setting namespaces and prefixes in a Java DOM document

I am trying to convert a ResultSet to an XML file. I first used this example for serialization.

import org.w3c.dom.bootstrap.DOMImplementationRegistry; import org.w3c.dom.Document; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSSerializer; ... DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance(); DOMImplementationLS impl = (DOMImplementationLS)registry.getDOMImplementation("LS"); ... LSSerializer writer = impl.createLSSerializer(); String str = writer.writeToString(document); 

After doing this work, I tried to validate my XML file, there were several warnings. One that he has no doctrine. So I tried another way to implement this. I came across a Transformer class. This class allows me to set the encoding, doctype, etc.

The previous implementation supports automatic namespace detection. Not.

 private static Document toDocument(ResultSet rs) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.newDocument(); URL namespaceURL = new URL("http://www.w3.org/2001/XMLSchema-instance"); String namespace = "xmlns:xsi="+namespaceURL.toString(); Element messages = doc.createElementNS(namespace, "messages"); doc.appendChild(messages); ResultSetMetaData rsmd = rs.getMetaData(); int colCount = rsmd.getColumnCount(); String attributeValue = "true"; String attribute = "xsi:nil"; rs.beforeFirst(); while(rs.next()) { amountOfRecords = 0; Element message = doc.createElement("message"); messages.appendChild(message); for(int i = 1; i <= colCount; i++) { Object value = rs.getObject(i); String columnName = rsmd.getColumnName(i); Element messageNode = doc.createElement(columnName); if(value != null) { messageNode.appendChild(doc.createTextNode(value.toString())); } else { messageNode.setAttribute(attribute, attributeValue); } message.appendChild(messageNode); } amountOfRecords++; } logger.info("Amount of records archived: " + amountOfRecords); TransformerFactory tff = TransformerFactory.newInstance(); Transformer tf = tff.newTransformer(); tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); tf.setOutputProperty(OutputKeys.INDENT, "yes"); BufferedWriter bf = createFile(); StreamResult sr = new StreamResult(bf); DOMSource source = new DOMSource(doc); tf.transform(source, sr); return doc; } 

While testing the previous implementation, I got a TransformationException: the namespace for the 'xsi' prefix was not declared. As you can see, I tried adding a namespace with the xsi prefix to the root element of my document. After testing, I still got an exception. What is the correct way to set namespaces and their prefixes?

Edit: Another problem that I encountered with the first version is that the last element in the XML document does not have the last three closing tags.

+6
source share
3 answers

You have not added the namespace declaration to the root directory of the node; you just declared the root node in the namespace, two completely different things. When creating the DOM, you need to reference the namespace on each relevant Node. In other words, when you add your attribute, you need to define its namespace (for example, setAttributeNS).

Side note. Although the XML namespaces look like URLs, they really are not. There is no need to use the URL class here.

+4
source

The correct way to install node in a namespaceAware document is:

 rootNode.createElementNS("http://example/namespace", "PREFIX:aNodeName"); 

So, you can replace "PREFIX" with your own prefix and replace "aNodeName" with the name of your node. In order not to have each node having its own namespace declaration, you can define namespaces as attributes in the node root directory as follows:

 rootNode.setAttribute("xmlns:PREFIX", "http://example/namespace"); 

Be sure to install:

 documentBuilderFactory.setNamespaceAware(true) 

Otherwise, you do not have a namespace identifier.

+27
source

Note that setting the xmlns prefix using setAttribute is incorrect. If you want, for example, to sign your DOM, you need to use setAttributeNS: element.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:PREFIX", "http://example/namespace");

+5
source

Source: https://habr.com/ru/post/915678/


All Articles