对元素的 DOM 属性序列进行排序

发布于 2024-10-02 06:44:03 字数 4542 浏览 2 评论 0原文

这个问题之前已经在stackoverflow中被问过:

设置属性的顺序

真的不可能吗?

使用 insertBefore 我想对元素的属性序列进行排序。具体来说,在下面的示例中,如何更改属性的顺序?使用 setAttribute 来自节点?无论哪种情况,顺序似乎都是自动发生的,尽管 insertBefore 肯定意味着可以指定顺序。

代码:

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();
    }
}

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();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

多情出卖 2024-10-09 06:44:03

XML 元素属性的排序不是 XML 信息集,因此实现(包括 DOM、解析器和解解析器)没有义务保留它。

实际上,这意味着是否可以通过 DOM API(例如使用 insertBefore)控制属性的顺序是特定于实现的,并且是否跨转换保留顺序也是特定于实现的。

我的建议是更改您的应用程序,使其不依赖于 XML 属性排序。

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.

错々过的事 2024-10-09 06:44:03

底层 XML 不支持它。也许您可以利用库的特定实现来获得您想要的顺序,但不能保证它会永远以这种方式工作。

这样想,属性是元素的描述性项目。如果你又高又瘦,那么你的属性实际上就没有自然的排序。并不是说高的必须先于瘦的,或者瘦的必须先于高的。同样,一辆火热、快速、红色的汽车与其他汽车的区别并不在于它是火热、快速和红色,而是快速、红色和火热。

从实际角度来看,您所能期望的最好结果就是从节点中删除所有属性,并弄清楚底层代码是如何工作的。在特定的情况下,对于特定的库版本,以正确的顺序添加所有属性可能会获得您希望的顺序。并不理想,但如果它对您来说很重要,那么任何解决方案都比没有好。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文