2012-02-21 45 views
1

我做与计算器的数据在Java中集和一些工作有一个这样的字符串:转换简单的XML行成一个优雅的地图

<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

为什么不直接将它解析为XML?另请参阅http://stackoverflow.com/questions/5231285/read-single-xml-line-with-java – 2012-02-21 21:53:48

+1

您还可以解释一下如何结束一个逐行处理XML文件的框架吗? – 2012-02-21 21:58:20

+0

将Hadoop与LineRecordReader配合使用。它将数据逐行传递给我,并将其分成不同的进程。 – 2012-02-21 21:59:15

回答

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。*库进行处理。它不像一个简单的String处理方法那样轻便,所以希望有人能想出更好的东西。将DocumentBuilder存储为静态最终变量将有助于加快处理速度,因为您无需每次都创建一个。

1

您可以为此使用SAX解析器。它按照您的要求逐行处理XML。

+0

我应该更清楚 - 我一次只能访问一行。并不是我不想逐行处理它们,我必须这样做。 – 2012-02-21 21:55:17

+0

你仍然可以使用SAX解析器,你只需要调用每一行的解析器。我认为这是可能的,但表现明智,这不是一个好的解决方案。在这种情况下,手动解析将比SAX解析器执行得更好。 – JProgrammer 2012-02-21 22:31:31

+0

我认为只要您注意重用解析器,SAX解析可能会合理执行。但是,是的,解析这样一个小文档时,仍然会有一个重大的启动开销。 – 2012-02-21 23:17:22

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