Android中操作XML——DOM篇
1 2 3 4 5 |
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; |
在Android开发中我们可以通过DOM、Sax、Pull这几种方法来操作XML。其中DOM是大家都比较熟悉的方法,如果使用过其他开发工具的人肯定也都用过相应的DOM方法来解析过XML。
要在Android中操作XML必须先要定义一个DocumentBuilderFactory实例,此实例用于设置一些解析时相关的属性,比如是否解析comment类型的节点、是否忽略xml文件内容中的空白字符等,另外比较重要的一点是,它的newDocumentBuilder函数是用来创建一个DocumentBuilder对象的。该类的实例由它本身的一个静态函数newInstance来创建。
1 |
DocumentBuilderFactory docBF = DocumentBuilderFactory.newInstance(); |
创建了DocumentBuilderFactory并设置相关的属性(如果需要)后,我们就可以创建一个DocumentBuilder对象了。DocumentBuilder对象是用来从各种源(输入流、文件、URL、InputSource)中载入XML文档的类,并不负责操作XML中的各节点和属性。
1 |
DocumentBuilder docB = docBF.newDocumentBuilder(); |
有了DocumentBuilder我们就可以从不同的源中载入xml文档了,我们需要使用Parse函数。如:
1 |
Document doc = docB.Parse("/mnt/sdcard/doc.xml"); |
如果是要从一个xml字符串中加载xml则可以使用如下方法
1 2 3 |
String xmlStr = ""; InputStream inputStream = new ByteArrayInputStream(xmlStr.getBytes()); Document doc = docB.parse(inputStream); |
也许你是要创建一个全新的XML文档并在此基础上添加数据,那么你可以使用如下代码:
1 |
Document doc = docB.NewDocument(); |
下面代码介绍如何读取XML中的内容,XML文件内容如下:
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="utf-8"?> <UserList> <User Name="Liu" ID="1"> <Website><![CDATA[http://svn1.bcoder.com]]></Website> <Intro>I come from hebei.</Intro> </User> <User Name="Zhang" ID="2"> <Website><![CDATA[http://www.desktoptool.net]]></Website> <Intro>I come from Shandong.</Intro> </User> </UserList> |
下面的代码读取XML内容并显示到一个EditText中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
DocumentBuilderFactory docBF = DocumentBuilderFactory.newInstance(); DocumentBuilder docB; try { docB = docBF.newDocumentBuilder(); String resStr = "你的XML字符串"; InputStream inputStream = new ByteArrayInputStream(resStr.getBytes()); Document doc = docB.parse(inputStream); Element rootNode = doc.getDocumentElement(); NodeList uNodeList = rootNode.getChildNodes(); for (int i=0; i<uNodeList.getLength()- 1; i++){ if (uNodeList.item(i).getNodeName().equals("User")) { etXmlValues.append("ID:" + uNodeList.item(i).getAttributes().getNamedItem("ID").getNodeValue()); etXmlValues.append("rn"); etXmlValues.append("Name:" + uNodeList.item(i).getAttributes().getNamedItem("Name").getNodeValue()); etXmlValues.append("rn"); for(Node cNode = uNodeList.item(i).getFirstChild(); cNode != null; cNode = cNode.getNextSibling()){ if (cNode.getNodeType() == Node.ELEMENT_NODE){ if (cNode.getNodeName().equals("Website")) { etXmlValues.append("WEB:" + cNode.getTextContent()); etXmlValues.append("rn"); } else if (cNode.getNodeName().equals("Intro")) { etXmlValues.append("INTRO:t" + cNode.getTextContent()); etXmlValues.append("rn"); } } } etXmlValues.append("rn"); } } } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } |
其中的几个常用的函数为:
getChildNodes(): 获取某节点下的所有子节点
getNodeName(): 获取节点的名称
getAttributes().getNamedItem(“ID”).getNodeValue(): 获取节点中属性名为ID的值
getFirstChild(): 获取某节点下的第一个子节点
getNextSibling(): 获取某个节点的紧邻的下一个节点
getNodeType(): 获取节点的类型,通过需要判断节点类型为Node.ELEMENT_NODE才继续解析,关于xml的节点类型请参考此文章
getTextContent(): 获取某节点中所包括的文本内容
向XML文件中添加数据的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public void SaveNewValues(View V) throws ParserConfigurationException, NotFoundException, SAXException, IOException, TransformerException{ EditText etnId = (EditText)findViewById(R.id.etAddId); EditText etnName = (EditText)findViewById(R.id.etAddName); EditText etnWebsite = (EditText)findViewById(R.id.etAddWebsite); EditText etnIntro = (EditText)findViewById(R.id.etAddIntro); String nId = etnId.getText().toString(); String nName = etnName.getText().toString(); String nWebsite = etnWebsite.getText().toString(); String nIntro = etnIntro.getText().toString(); DocumentBuilderFactory docBF = DocumentBuilderFactory.newInstance(); DocumentBuilder docB = docBF.newDocumentBuilder(); //Document doc = docB.newDocument(); Document doc = docB.parse(getResources().openRawResource(R.raw.sample_xml)); Element rootNode = doc.getDocumentElement(); Element nUNode = doc.createElement("User"); rootNode.appendChild(nUNode); nUNode.setAttribute("ID", nId); nUNode.setAttribute("Name", nName); Node nodeWeb = doc.createElement("Website"); nodeWeb.appendChild(doc.createCDATASection(nWebsite)); nUNode.appendChild(nodeWeb); Node nodeIntro = doc.createElement("Intro"); nodeIntro.appendChild(doc.createTextNode(nIntro)); nUNode.appendChild(nodeIntro); TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(); Result result = new StreamResult(new File("/mnt/sdcard/doc.xml")); Source source = new DOMSource(doc); transformer.transform(source, result); } |
其他问题:
1. 使用该方法解析xml时出现Unexpected token (position:TEXT @1:2 in java.io.StringReader@40e31480) 的错误,解决办法:因为要解析的xml文件使用的是UTF8带BOM的格式,所以在解析的时候出现错误,将xml的编码格式改为UTF8无BOM格式后问题解决。