我正在使用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结构(所有行)。我必须一次做一行。
答案 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;
}
}