如何在不改变属性顺序的情况下将xml节点转换为字符串?

时间:2014-02-26 11:30:09

标签: java xml xml-parsing

我正在尝试使用以下代码将XML节点转换为String:

private String nodeToString(final Node node) {
    final StringWriter stringWriter = new StringWriter();
    try {
        final Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.setOutputProperty(OutputKeys.INDENT, "no");
        transformer.transform(new DOMSource(node), new StreamResult(stringWriter));

    } catch (final TransformerException e) {
        JOptionPane.showMessageDialog(this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
    }
    return stringWriter.toString();
}

我的问题是它按字母顺序格式化XML节点的属性。我是否可以申请忽略Node属性的格式化?

2 个答案:

答案 0 :(得分:0)

DOM API does not preserve attribute order

  

NamedNodeMaps未按任何特定顺序维护

如果您有Node,那么您已经丢失了任何属性排序。考虑一下这个XML:

<?xml version="1.0" encoding="UTF-8"?>
<!-- attrs.xml -->
<attrs
  a="a"
  z="z"
  b="b"
  m="m" />

无法保证此应用程序输出的顺序:

import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;

public class Attrs {
  public static void main(String[] args) throws Exception {
    NamedNodeMap attrs = DocumentBuilderFactory.newInstance()
        .newDocumentBuilder()
        .parse("attrs.xml")
        .getElementsByTagName("attrs")
        .item(0)
        .getAttributes();
    for (int i = 0; i < attrs.getLength(); i++) {
      Attr attribute = (Attr) attrs.item(i);
      System.out.println(attribute.getName() + "=" + attribute.getValue());
    }
  }
}

如果它们是按字母顺序排列的,那么这只是实施副作用,而不是要求。如果属性顺序对您很重要,那么您使用的是错误的工具。

答案 1 :(得分:0)

我弄清楚如何执行此操作,我已读取xml文件,并从该xml文件中只读取特定节点作为字符串。并对字符串应用操作以符合我的条件。通过这样做显然我无法利用Parser API,但这满足了我的要求。以下是我的代码段:

/**
 * @param in InputStream of xml file
 */
private String getNodeString(InputStream in) throws IOException {

    String nodeString = "";
    InputStreamReader is = new InputStreamReader(in);
    StringBuilder sb = new StringBuilder();
    BufferedReader br = new BufferedReader(is);
    String read = br.readLine();

    String fileData;

    while (read != null) {
        //System.out.println(read);
        sb.append(read);
        read = br.readLine();
    }

    fileData = sb.toString().trim();

    // Start index of node
    int start = fileData.indexOf("<" + mSignedNode);
    // End index of node, next node name
    int end = fileData.indexOf("</Configuration>");

    nodeString = fileData.substring(start, end);
    return nodeString.trim();
}

该方法非常脏,但您可以传递参数来查找起始索引和结束索引。 希望这会帮助某人,而不仅仅是关闭他们的问题;)