优雅地将简单的XML行转换为Map

时间:2012-02-21 21:51:16

标签: java xml

我正在使用Java中的stackoverflow数据集进行一些工作,并且有一个这样的字符串:

 <row Id="1" PostId="35314" Score="8" Text="not sure why this is getting
     downvoted -- it is correct! Double check it in your compiler if you
     don't believe him!" CreationDate="2008-09-06T08:07:10.730" UserId="1" />

(为了便于阅读而添加了新行)

假设上面的数据是字符串,那么将它转换为Map<String, String>的最优雅方式是什么,其中键是标签("Id""Score" ,. ..)和值是包含值("1""35314",...)的字符串?我想优雅,可读,简洁地做到这一点,因为很多人都会看到这段代码。我写了一些东西,它做各种字符串操作,它只是丑陋。

在我使用的框架中,我必须一次处理一行,因此我无法一次解析整个XML结构(所有行)。我必须一次做一行。

5 个答案:

答案 0 :(得分:4)

public static Map<String, String> transformXmlToMap(String xml) {
    Document doc = null;
    try {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(false);
        DocumentBuilder bldr = factory
                .newDocumentBuilder();

        doc = bldr.parse(new ByteArrayInputStream(xml.getBytes()));
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }

    Map<String, String> map = new HashMap<String, String>();
    NamedNodeMap attributeMap = doc.getDocumentElement().getAttributes();

    for (int i = 0; i < attributeMap.getLength(); ++i) {
        Attr n = (Attr) attributeMap.item(i);

        map.put(n.getName(), n.getValue());
    }

    return map;
}

这将使用org.w3c。*库进行处理。它不像简单的字符串处理方法那样轻量级,所以希望有人可以提出更好的东西。将DocumentBuilder存储为静态最终变量将有助于加快处理速度,因为您不需要每次都创建一个。

答案 1 :(得分:2)

请参阅JAXB - HashMap主题以获取可能的解决方案。

答案 2 :(得分:1)

您可以使用SAX解析器。它根据您的要求逐行处理XML。

答案 3 :(得分:1)

如果你选择了SAX,你应该扩展DefaultHandler类,就像那个例子一样。

import java.util.HashMap;
import java.util.Map;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class RowDefaultHandler extends DefaultHandler {

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        if (!"row".equals(qName)) {
            return;
        }

        Map<String, String> row = new HashMap<String, String>();

        for (int i = 0; i < attributes.getLength(); i++) {
            row.put(attributes.getQName(i), attributes.getValue(i));
        }

        System.out.println(row);
    }

}

用法:

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class RowDefaultHandlerUsage {

    public static void main(String...args) throws Exception {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();

        CharSequence data = new StringBuilder()
            .append("<rows>")
                .append("<row Id=\"1\" PostId=\"35314\" Score=\"8\" />")
                .append("<row Id=\"2\" PostId=\"35315\" Score=\"3\" />")
            .append("<rows>");
        InputStream source = new ByteArrayInputStream(data.toString().getBytes());

        RowDefaultHandler rowHandler = new RowDefaultHandler();
        parser.parse(source, rowHandler);
    }

}

输出:

{Id=1, PostId=35314, Score=8}
{Id=2, PostId=35315, Score=3}

答案 4 :(得分:0)

这是在mrdp.utils中找到的。其他任何人都用核心Java编写了这个。

public class MRDPUtils {

    public static final String[] REDIS_INSTANCES = { "p0", "p1", "p2", "p3",
            "p4", "p6" };

    // This helper function parses the stackoverflow into a Map for us.
    public static Map<String, String> transformXmlToMap(String xml) {
        Map<String, String> map = new HashMap<String, String>();
        try {
            String[] tokens = xml.trim().substring(5, xml.trim().length() - 3)
                    .split("\"");

            for (int i = 0; i < tokens.length - 1; i += 2) {
                String key = tokens[i].trim();
                String val = tokens[i + 1];

                map.put(key.substring(0, key.length() - 1), val);
            }
        } catch (StringIndexOutOfBoundsException e) {
            System.err.println(xml);
        }

        return map;
    }
}