this question has been asked before in stackoverflow:
setting order of attributes
It's really not possible?
Using insertBefore I want to order the sequence of attributes for an element. Specifically, in the example below, how do I change the order of the attributes? Would it be easier to just use setAttribute from a node? In either case, the order seems to happen automagically, although insertBefore certainly implies that order can be specified.
code:
package xml;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class Main {
private static final Logger logger = Logger.getLogger(Main.class.getName());
/**
* catches errors
*/
public Main() {
try {
createDoc();
} catch (ParserConfigurationException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (TransformerConfigurationException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (TransformerException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void createDoc()
throws ParserConfigurationException, TransformerConfigurationException, TransformerException, IOException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setIgnoringComments(false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.newDocument();
doc.setXmlStandalone(true);
Comment comment = doc.createComment(" nodes ");
doc.appendChild(comment);
Element root = doc.createElement("foo");
root.setAttribute("Version", "1.0");
doc.appendChild(root);
Element bar = doc.createElement("bar");
Element baz = doc.createElement("baz");
Element child1 = doc.createElementNS("foo", "bar");
child1.setPrefix("prefix1");
Attr attr1 = doc.createAttribute("attr1");
attr1.setValue("val1");
Element child2 = doc.createElementNS("foo", "bar");
child2.setPrefix("prefix2");
Attr attr2 = doc.createAttribute("attr2");
attr2.setValue("val2");
baz.setAttributeNode(attr2);
baz.setAttributeNode(attr1);
root.appendChild(bar);
bar.appendChild(baz);
writeToFile(doc);
}
private void writeToFile(Document doc)
throws TransformerConfigurationException, TransformerException, IOException {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
transformerFactory.setAttribute("indent-number", new Integer(2));
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"开发者_如何学运维);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
logger.log(Level.INFO, "\n{0}", sw.toString());
result = new StreamResult(new FileWriter("test.xml"));
transformer.transform(source, result);
}
public static void main(String args[]) {
Main main = new Main();
}
}
The ordering of the attributes of an XML element is not part of the XML information set, and therefore implementations (including DOMs, parsers and unparsers) are not obliged to preserve it.
In practice, this means that it is implementation specific as to whether you can control the order of the attributes via the DOM APIs (e.g. using insertBefore), and it is implementation specific whether the ordering will be preserved across transformations.
My advice is to change your application so that it does not rely on XML attribute ordering.
It's not supported in the underlying XML. Perhaps you can exploit a library's particular implementation to get the order you want, but there will be no guarantees it will work that way forever.
Think of it this way, an attribute is a descriptive item of an element. If you are tall and skinny, then there's really no natural ordering of your attributes. It isn't like tall must come before skinny, or skinny before tall. Likewise, a hot, fast, red car isn't differentiated from other cars by being hot, fast, and red instead of fast, red, and hot.
On a practical side, the best you can hope for is to remove all attributes from the node, and figure out how the underlying code works. Adding all attributes back in the right order might obtain the order you wish, for that specific library version, under that particular set of circumstances. Not ideal, but if it is that important to you, any solution is better than none.
精彩评论