DOM解析器

来源:互联网 发布:颜值网络句子 编辑:程序博客网 时间:2024/06/05 07:56
1.DOM标准

DOM(Document Object Model,文档对象模型)是W3C制定的一套规范标准,即规定了解析文件的接口。各种语言可以按照DOM规范去实现这些接口,给出解析文件的解析器。

各种基于DOM规范解析器必须按照DOM规范在内存中建立数据,DOM规范的核心是树模型。对于解析XML文件的解析器,解析器通过读入XML文件在内存中建立一个树,也就是说XML文件的标记、标记的文本内容、实体等都会和内存中树的某个节点相对应。一个应用程序可以方便地操作内存中树的节点来处理XML文档,获取自己所需要的数据。


2.DOM解析器

用 DOM 解析模型的优点是编程容易,开发人员只需要调用建树的指令,然后利用navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然而由于使用 DOM 解析器的时候需要处理整个 XML 文档,所以对性能和内存的要求比较高,尤其是遇到很大的 XML 文件的时候。由于它的遍历能力,DOM 解析器常用于 XML 文档需要频繁的改变的服务中。W3C推荐使用DOM解析。



3.DOM和XML文件的互相转化

DOM解析器是DocumentBuilder类的实例。


XML转化为DOM对象

首先使用javax.xml.parsers包中的DocumentBuilderFactory类调用其类方法newInstance()实例化一个DocumentBuilderFactory对象:

[java] view plaincopyprint?
  1. DocumentBuilderFactory factory= DocumentBuilderFactory. newInstance();
DocumentBuilderFactory  factory= DocumentBuilderFactory. newInstance();

然后factory对象调用newDocumentBuilder()方法返回一个DocumentBuilder对象(称做DOM解析器),DocumentBuilder 类在javax.xml.parsers包中。例如:
[java] view plaincopyprint?
  1. DocumentBuilder builder=factory. newDocumentBuilder();
DocumentBuilder  builder=factory. newDocumentBuilder();

最后builder对象调用public Document parse(File f)方法解析参数f指定的文件,并将解析内容以对象的形式返回,该对象是实现了Document接口的一个实例,Document 接口在org.w3c.dom包中。例如:
[java] view plaincopyprint?
  1. Document document= builder. parse(new File("/mnt/sdcard/river.xml")) ;
Document  document= builder. parse(new File("/mnt/sdcard/river.xml")) ;

现在,应用程序只要分析内存中的树状结构数据Document,就可以获得XML文件中的各种数据了。


DOM解析器经常使用下述3个方法解析XML文件:


public Document parse(File f) throws SAXException, IOException

public Document parse(InputStream in) throws SAXException, IOException

public Document parse(String uri) throws SAXException, IOException


其中:

方法parse(File f)可以解析参数f指定的XML文件,例如:

[java] view plaincopyprint?
  1. File f= new File("/mnt/sdcard/river.xml");
  2. Document document= builder. parse(f) ;
File f= new File("/mnt/sdcard/river.xml");Document  document= builder. parse(f) ;

直接这样指定assets下路径是不幸的。File file = new File(" file:///android_asset/river.xml");原因是assets下的资源为原生的,只能用流的方式读取,而且不能向assets目录下写。




方法parse(InputStream in)可以解析输入流参数in指向的XML文件,例如:

[java] view plaincopyprint?
  1. AssetManager assetManager = act.getAssets();
  2. InputStream inputStream = assetManager.open("price.xml"); ;
  3. Document document= builder. parse(inputStream) ;
AssetManager assetManager = act.getAssets();InputStream inputStream  = assetManager.open("price.xml"); ;Document  document= builder. parse(inputStream) ;


方法parse(String uri)可以解析参数uri指定的一个有效的资源,如果uri是一个链接地址,该链接地址必须是可以访问的,例如:

[java] view plaincopyprint?
  1. String uri="http://192.168.2.1/price.xml";
  2. Document document= builder. parse(uri) ;
String  uri="http://192.168.2.1/price.xml";Document  document= builder. parse(uri) ;

除了通过parse方法得到Document对象外,还可以直接创建Document对象:

[java] view plaincopyprint?
  1. builder.newDocument();//可以创建一个Document,然后修改它
builder.newDocument();//可以创建一个Document,然后修改它

DOM对象转化为XML文件

解析器通过在内存中建立和XML结构相对应的树状结构数据,使得应用程序可以方便地获得XML文件中的数据,同时提供了使用内存中的树状结构数据建立一个XML文件的API,即使用解析器得到的Document对象建立一个新的XML文件。但是需要注意的是,Android2.1中没有相应的类包,从2.2开始才加入了。

解析器的parse方法将整个被解析的XML文件封装成一个Document节点返回,我们可以对Document节点进行修改,然后使用 Transformer对象将一个Document节点变换为一个XML文件。

步骤如下:

首先使用javax.xml.transform包中的TransformerFactory类建立一个对象,

[java] view plaincopyprint?
  1. TransformerFactory transFactory=TransformerFactory. newInstance()
TransformerFactory transFactory=TransformerFactory. newInstance()

然后transFactory对象调用newTransformer()方法得到一个Transformer对象,Transformer类在javax.xml.transform包中。

[java] view plaincopyprint?
  1. Transformer transformer=transFactory. newTransformer();
Transformer transformer=transFactory. newTransformer();

然后将被变换的Document对象封装到一个DOMSource对象中,DOMSource类在javax.xml.transform.dom包中。

[java] view plaincopyprint?
  1. DOMSource domSource=new DOMSource(document);
DOMSource  domSource=new DOMSource(document);

再然后将变换得到XML文件对象封装到一个StreamResult对象中,StreamResult类在javax.xml.transform.stream包中。
[java] view plaincopyprint?
  1. File file=new File("/mnt/sdcard/newXML.xml");//生成在SDCard下名为newXML的XML文件
  2. FileOutputStream out=new FileOutputStream(file);
  3. StreamResult xmlResult=new StreamResult(out);
File file=new File("/mnt/sdcard/newXML.xml");//生成在SDCard下名为newXML的XML文件FileOutputStream out=new FileOutputStream(file);StreamResult xmlResult=new StreamResult(out);

最后,Transformer 对象transformer 调用transform方法实施变换:
[java] view plaincopyprint?
  1. transformer.transform(domSource, xmlResult);
transformer.transform(domSource, xmlResult);


注意:以上用到了写文件创建文件等,所以需要在AndroidManifest.xml中加入访问SDCard的权限

<!--在SDCard中创建与删除文件权限 -->

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

<!--往SDCard写入数据权限 -->

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>



1. 节点(Node)

解析器调用parse方法返回一个实现了Document接口的实例,该实例也称做Document对象,应用程序可以从Document节点的子孙节点中获取整个XML文件中数据的细节,它是由实现了Node接口的实例组成的树状结构数据,这些实例称做Document对象中的节点。实际上Document接口也是Node接口的子接口,也就是说,parse方法将整个被解析的XML文件封装成一个节点返回(XML文件和内存中的Document节点相对应),因此,我们也可以称Document对象为Document节点。


Document对象中的节点形成树状结构,也就是说XML文件的标记、标记的文本内容、实体等都会和对象Document中的某个节点相对应。应用程序可以从Document节点的子孙节点中获取整个XML文件中数据的细节。


按照DOM规范,Node接口有如下的子接口:
Attr, CDATASection, CharacterData, Comment, Document, DocumentFragment, DocumentType, Element, Entity, EntityReference, Notation, ProcessingInstruction, Text

任何实现上述某个接口的类的实例都称做一个节点。



2.Node的常用方法


short getNodeType()
返回一个表示节点类型的常量(Node接口规定的常量值),例如,对于Element节点,getNodeType()方法返回的值为:Node.ELEMENT_NODE


NodeList getChildNodes()
返回一个由当前节点的所有子节点组成的NodeList对象。


Node getFirstChild()
返回当前节点的第一个子节点。


Node getLastChild()
返回当前节点的最后一个子节点。


NodeList getTextContent()
返回当前节点及所有子孙节点中的文本内容。



3.节点的子孙关系
为了解析规范的XML文件,DOM规范规定了各种类型节点之间可以形成的子孙关系,比如,Document节点有且仅有一个Element节点,也可以有一个DocumentType节点(规范的XML文件有且仅有一个根标记,也可以有一个与其关联的DTD文件),Element节点可以有Element子节点和Text子节点(规范的XML文件中的标记可以有子标记和文本)。

 

Document节点


Document节点的两个直接子节点的类型分别是DocumentType类型和Element类型,其中的DocumentType节点对应着XML文件所关联的DTD文件,通过进一步获取该节点子孙节点来分析DTDL文件中的数据;而其中的Element类型节点对应着XML文件的根节点,通过进一步获取该Element类型节点子孙节点来分析XML文件中的数据。


Document 节点经常使用下列方法获取和该节点相关的信息。


Element getDocumentElement()

返回当前节点的Element子节点。


DocumentType getDoctype()

返回当前节点的DocumentType子节点。


NodeList getElementsByTagName(String name)

返回一个NodeList对象,该对象由当前节点的Element类型子孙节点组成,这些子孙节点的名字由参数name指定。


NodeList getElementsByTagNameNS(String namespaceURI,String localName)

返回一个NodeList对象,该对象由当前节点的Element类型子孙节点组成, 这些子孙节点的名字由参数localName指定,名称空间由参数namespaceURI 指定。


String getXmlEncoding()

返回XML文件使用的编码,即XML声明中encoding属性的值。


boolean getXmlStandalone()

返回XML声明中的standalone属性的值。未指定时返回NULL

standalone 用来表示该文件是否呼叫其它外部的文件。 这里所指的外部文件其实就是查检XML是不是有效的约束文件,或是DTD或是Schema


String getXmlVersion()

返回XML声明中的version属性的值


其中getXmlEncoding getXmlVersion getXmlStandalong在Android2.1中是没有的。


要解析的XML文件:

[java] view plaincopyprint?
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <rivers>
  3. <river name="灵渠" length="605">
  4. <introduction>
  5. 灵渠在广西壮族自治区兴安县境内,是世界上最古老的运河之一,有着“世界古代水利建筑明珠”的美誉。灵渠古称秦凿渠、零渠、陡河、兴安运河,于公元前214年凿成通航,距今已2217年,仍然发挥着功用。
  6. </introduction>
  7. <imageurl>
  8. http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg
  9. </imageurl>
  10. </river>
  11. <river name="胶莱运河" length="200">
  12. <introduction>
  13. 胶莱运河南起黄海灵山海口,北抵渤海三山岛,流经现胶南、胶州、平度、高密、昌邑和莱州等,全长200公里,流域面积达5400平方公里,南北贯穿山东半岛,沟通黄渤两海。胶莱运河自平度姚家村东的分水岭南北分流。南流由麻湾口入胶州湾,为南胶莱河,长30公里。北流由海仓口入莱州湾,为北胶莱河,长100余公里。
  14. </introduction>
  15. <imageurl>
  16. http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg
  17. </imageurl>
  18. </river>
  19. <river name="苏北灌溉总渠" length="168">
  20. <introduction>
  21. 位于淮河下游江苏省北部,西起洪泽湖边的高良涧,流经洪泽,青浦、淮安,阜宁、射阳,滨海等六县(区),东至扁担港口入海的大型人工河道。全长168km。
  22. </introduction>
  23. <imageurl>
  24. http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg
  25. </imageurl>
  26. </river>
  27. </rivers>
<?xml version="1.0" encoding="utf-8"?><rivers> <river name="灵渠" length="605">     <introduction>      灵渠在广西壮族自治区兴安县境内,是世界上最古老的运河之一,有着“世界古代水利建筑明珠”的美誉。灵渠古称秦凿渠、零渠、陡河、兴安运河,于公元前214年凿成通航,距今已2217年,仍然发挥着功用。     </introduction>      <imageurl>      http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg     </imageurl>   </river>     <river name="胶莱运河" length="200">     <introduction>      胶莱运河南起黄海灵山海口,北抵渤海三山岛,流经现胶南、胶州、平度、高密、昌邑和莱州等,全长200公里,流域面积达5400平方公里,南北贯穿山东半岛,沟通黄渤两海。胶莱运河自平度姚家村东的分水岭南北分流。南流由麻湾口入胶州湾,为南胶莱河,长30公里。北流由海仓口入莱州湾,为北胶莱河,长100余公里。     </introduction>      <imageurl>      http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg     </imageurl>   </river>     <river name="苏北灌溉总渠" length="168">     <introduction>      位于淮河下游江苏省北部,西起洪泽湖边的高良涧,流经洪泽,青浦、淮安,阜宁、射阳,滨海等六县(区),东至扁担港口入海的大型人工河道。全长168km。     </introduction>      <imageurl>      http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg     </imageurl>   </river> </rivers>


 

[java] view plaincopyprint?
  1. private Document parseXML(InputStream is)
  2. { if(is == null)return null;
  3. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  4. // dbf.setValidating(true);//设置检查XML文件的有效性
  5. // dbf.setIgnoringElementContentWhitespace(true);//设置忽略空白
  6. // dbf.setNamespaceAware(false);//设置为true时,由DocumentBuilderFactory产生的DOM解析器支持名称空间
  7. DocumentBuilder db = null;//DOM解析器
  8. Document doc = null;
  9. try {
  10. db = dbf.newDocumentBuilder();
  11. } catch (ParserConfigurationException e) {
  12. // TODO Auto-generated catch block
  13. e.printStackTrace();
  14. }
  15. try {
  16. doc = db.parse(is);//可以通过解析XML得到一个Document
  17. // db.newDocument();//可以创建一个Document,然后修改它
  18. } catch (SAXException e) {
  19. // TODO Auto-generated catch block
  20. e.printStackTrace();
  21. } catch (IOException e) {
  22. // TODO Auto-generated catch block
  23. e.printStackTrace();
  24. }
  25. DocumentType docType = doc.getDoctype();
  26. String xmlEncoding = doc.getXmlEncoding();//android2.1不支持
  27. String xmlVersion = doc.getXmlVersion();
  28. boolean isAlone = doc.getXmlStandalone();//android2.1不支持
  29. NodeList list = doc.getElementsByTagName("river");
  30. int length = list.getLength();
  31. for(int k =0;k<length;k++)
  32. {
  33. Node node = list.item(k);
  34. String nodeName = node.getNodeName();
  35. String textContent = node.getTextContent();
  36. //取得当前节点下的所有Text节点内容,这里就包括introduction下和imageUrl下的Text以及空格
  37. }
  38. return doc;
    private Document  parseXML(InputStream is)    {   if(is == null) return null;    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();//    dbf.setValidating(true);//设置检查XML文件的有效性//    dbf.setIgnoringElementContentWhitespace(true);//设置忽略空白//    dbf.setNamespaceAware(false);//设置为true时,由DocumentBuilderFactory产生的DOM解析器支持名称空间    DocumentBuilder db = null; //DOM解析器    Document doc = null;        try {    db = dbf.newDocumentBuilder();} catch (ParserConfigurationException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {     doc = db.parse(is);//可以通过解析XML得到一个Document//     db.newDocument();//可以创建一个Document,然后修改它     } catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}DocumentType docType =  doc.getDoctype();String xmlEncoding = doc.getXmlEncoding();//android2.1不支持String xmlVersion = doc.getXmlVersion();        boolean isAlone = doc.getXmlStandalone();//android2.1不支持        NodeList list = doc.getElementsByTagName("river");    int length = list.getLength();    for(int k = 0;k<length;k++)    {    Node node = list.item(k);    String nodeName = node.getNodeName();    String textContent = node.getTextContent();//取得当前节点下的所有Text节点内容,这里就包括introduction下和imageUrl下的Text以及空格        }return doc;


其中getXmlEncoding方法在XML设置了encoding的情况下,取不到,不知道为什么。

 

Element节点


Element节点是Document节点的最重要的子孙节点,因为被解析的XML文件的标记对应着这样类型的节点。表示Element节点的常量是Node.ELEMENT_NODE,一个节点用
short getNodeType()方法返回的值如果等于Node.ELEMENT_NODE,那么该节点就是Element节点。



Element节点经常使用下列方法获取和该节点相关的信息。


String getTagName()

返回该节点的名称,该名称就是此节点对应的XML中的标记名称。


String getAttribute(String name)

返回该节点中参数name指定的属性值,该属性值是此节点对应的XML标记中的属性值。


NodeList getElementsByTagName(String name)

返回一个NodeList对象,该对象由当前节点的Element类型子孙节点组成,这些子孙节点的名字由参数name指定。
NodeList getElementsByTagNameNS(String namespaceURI,String localName)返回一个NodeList对象,该对象由当前节点的Element类型子孙节点组成,这些子孙节点的 名字由参数localName指定,名称空间由参数namespaceURI 指定。


boolean hasAttribute(String name)

判断当前节点是否有名字是参数name指定的属性。


boolean hasAttributeNS(String namespaceURI, String localName)

判断当前节点是否有名字是参数name指定、名称空间是namespaceURI指定的属性。


String getTextContent() Android 2.1没有本API


getTagName和getNodeName的区别

getTagName()方法是Element接口中的方法,getNodeName()方法是Element接口从Node接口继承的方法。对于Element节点,getTagName()和getNodeName()返回的都是Element节点对应的XML文件中标记的名称。

 

Text节点


规范的XML文件的非空标记可以有子标记和文本内容。在DOM规范中,解析器使用Element节点封装标记,用Text节点封装标记的文本内容,即Element节点可以有Element子节点和Text节点。例如,对于下列标记:

[java] view plaincopyprint?
  1. <姓名>张小三
  2. <性别>男</性别>
  3. <年龄>23</年龄>
  4. </姓名>
<姓名>张小三<性别>男</性别><年龄>23</年龄></姓名>


该标记对应的Element节点共有7个子孙节点,其中2个Element子节点、3个Text子节点和2个Text孙节点。这些节点和XML中的标记及文本有如下的对应关系。
2个Element子节点分别对应“姓名”标记的2个子标记:“性别”和“年龄”。3个Text子节点分别对应着:“<姓名>”与“<性别>”之间的文本、“</性 别>”与“<年龄>”之间的空白类字符、“</年龄”与“</姓名>”之间的空白类字符。两个Text孙节点分别对应标记“性别”和“年龄”的文本内容。


表示Text节点的常量是Node.TEXT_NODE,一个节点调用short getNodeType()方法返回的值如果等于Node.TEXT_NODE,那么该节点就是Text节点。
Text节点使用String getWholeText()方法获取节点中的文本(包括其中的空白字符)。Android2.1中没有本API


注意:对于Text节点,getNodeName()方法返回的是“#text”。


对于应用程序而言,Text节点是较重要的节点,因为Text节点封装着XML标记中的文本数据。


Attr节点

在XML文件中,属性并不是标记的子标记,因此,在DOM规范中,Att节点也不是Element节点的子节点。


如果想解析XML文件中标记的属性,必须让对应的Element节点调用NamedNodeMap getAttributes()方法。该方法返回的NamedNodeMap对象由节点组成,这些节点可以被转换为Attr节点。Attr节点通过调用String getName()方法返回属性的名字,调用String getValue()方法返回属性的值。



处理空白

标记之间的缩进区域是为了使得XML文件看起来更美观而形成的,但解析器并不知道这一点,所以解析器仍然认为它们是有用的文本数据(由空白类字符组成)

人们习惯上称标记之间的缩进区是可忽略空白,这实际上不是很准确,因为XML文件的标记可以有文本和子标记(混合内容),在这种情况下,标记之间的区域中就可能包含非空白的字符内容。
如果我们不允许标记有混合内容,即标记要么只有子标记要么只有文本,在这种情形下,称标记之间的缩进区域是可忽略空白就比较恰当,这些空白区确实使得XML文件看起来更加美观,也是它们存在的惟一目的。


如果想让DOM解析器忽略缩进空白,即这些缩进空白不在Document中形成Text节点,那么XML文件必须是有效的,而且所关联的DTD文件必须规定XML文件的标记不能有混合内容,同时DocumentBuilderFactory对象在给出DOM解析器之前,必须调用setIgnoringElementContentWhitespace(boolean whitespace)进行设置,将参数whitespace的值设为true。


验证规范性和有效性

通过DocumentBuilderFactory对象factory事先设置是否检查XML文件的有效性,如:factory.setValidating(true);

 

DocumentType节点


DocumentType节点是Document节点的一个子节点。我们已经知道,解析器的parse方法将整个被解析的XML文件封装成一个Document节点返回,Document节点的两个子节点的类型分别是DocumentType类型和Element类型,其中的DocumentType节点对应着XML文件所关联的DTD文件,通过进一步获取该节点子孙节点来分析DTD文件中的数据。Document节点调用getDoctype() 返回当前节点的DocumentType子节点。


获取DTD的基本信息


假如XML文件中的DOCTYPE声明为:<!DOCTYPE 房子 PUBLIC "-//ISO88//beijing//ForXML/Ch" "b1.dtd",那么

DocumentType节点调用getName()方法返回的是:房子
调用getPublicId()方法返回的是:-//ISO88//beijing//ForXML/Ch
调用getSystemId()方法返回的是:b1.dtd


一个XML文件可以关联一个外部DTD或一个内部DTD,也可二者皆有(见第3.9节)。如果XML关联一个内部DTD,DocumentType节点调用getInternalSubset()方法可以返回内部DTD的内容。


获取实体


DTD文件中可以定义实体,然后与该DTD文件关联的XML文件可以通过实体引用使用该实体。实体又分为内部实体和外部实体,所谓内部实体就是实体的内容已经包含在DTD文件本身中;而外部实体是指实体的内容是DTD文件以外的其他文件。
解析器将实体封装为Entity节点,DocumentType节点调用
NamedNodeMap getEntities()
方法可以得到全部的实体,该方法返回的NamedNodeMap对象由节点组成,这些节点可以被转换为Entity节点。Entity节点通过调用getTextContent()方法返回实体,如果实体是一个外部文件,Entity节点通过调用getInputEncoding()方法可以返回解析该实体所使用的编码;如果是内部实体,getInputEncoding()方法返回null。


CDATASection节点


在XML文件中,标记内容中的文本数据不可以含有左尖括号、右尖括号、与符号、单引号和双引号这些特殊字符,如果想使用这些字符,办法之一是通过实体引用,如果需要许多这样的字符,文本数据中就会出现很多实体引用或字符引用,导致文本数据的阅读变得困难。使用CDATA(Character Data)段可以解决这一问题,CDATA段用“<![CDATA[”作为段的开始,用“]]>”作为段的结束,段开始和段结束之间称为CDATA段的内容,解析器不对CDATA段的内容做分析处理,因此,CDATA段中的内容可以包含任意的字符。
在DOM规范中,解析器使用CDATASection节点封装CDATA段,CDATASection节点可以是Element的节点的子节点。


节点数目的计算办法如下。


首先将标记中交替出现的普通文本和CDATA段按照它们在标记中出现的先后顺序排列,如:
普通文本1 CDATA段1 普通文本2 CDATA段2 普通文本3


那么该标记对应的Element节点的子节点顺序如下。


1 / Text节点:从“普通文本1”到“普通文本3”的区域,节点的文本内容是普通文本和CDATA段中的内容。
2 / CDATASection节点:从“CDATA段1”到“普通文本3”的区域,节点的文本内容是普通文本和CDATA段中的内容。
3 / Text节点:从“普通文本2”到“普通文本3”的区域,节点的文本内容是普通文本和CDATA段中的内容。
4 / CDATASection节点:从“CDATA段2”到“普通文本3”的区域,节点的文本内容是普通文本和CDATA段中的内容。
5 / Text节点:“普通文本3”,节点的文本内容是普通文本。



表示CDATASection节点的常量是Node.CDATA_SECTION_NODE,一个节点调用short getNodeType()方法返回的值如果等于Node.CDATA_SECTION_NODE,那么该节点就是CDATASection节点。CDATASection节点使用String getWholeText()方法获取节点中的文本,即CDATA段中的文本(包括其中的空白字符)。


注意:对于CDATASection节点,getNodeName()方法返回的是“#cdata-section”。

更多0

原创粉丝点击