[请教]DOM解析XML:getFirstChild()和getNextSibling()的疑问

kit_147 2008-11-07 03:20:48
情况:
用DOM解析一XML文件,其中有用到XPath求值器
在解析中获取结点时,出现这种情况:明明应该得到的是DOCUMENT_NODE类型的结点,但是得到的是TEXT_NODE

.xml文件结构:
<?xml version="1.0" encoding="GB2312"?>
<category>
<pattern>你 家 在 [哪里|什么地方|什么位置]</pattern>
<template>
<random>
<li>你猜看</li>
<li>长沙啊</li>
<li>不告诉你</li>
</random>
</template>
</category>

</category>
<category>
<pattern>家庭 地址 是 多少</pattern>
<template>
<srai>你 家 在 [哪里|什么地方|什么位置]</srai>
</template>
</category>

JAVA代码:

Document document = getDocument();
Node rootNode = document.getFirstChild();

NodeList nodeCategorys = XPathAPI.selectNodeList(rootNode, "//category");
for (int i = 0; i < nodeCategorys.getLength(); i++){
if (nodeCategorys.item(i).hasChildNodes()){
Node template = XPathAPI.selectSingleNode(nodeCategorys.item(i), "template");

//【1】这行如果写成template.getFirstChild(),则templateChild就是TEXT_NODE类型
Node templateChild = template.getFirstChild().getNextSibling();

if (templateChild.getNodeName().equals("srai")) { continue; }
if (templateChild.getNodeName().equals("random")){
ItemVo vo = new ItemVo();
Node patternNode = nodeCategorys.item(i).getFirstChild().getNextSibling();//这行问题同【1】

String pattern = patternNode.getFirstChild().getNodeValue();//【2】

……
……

NodeList nodeLi = XPathAPI.selectNodeList(templateChild,"li");
for (int j = 0; j < nodeLi.getLength(); j++)
{
Node liNode = nodeLi.item(j);//【3】这里又不用加getNextSibling()了,取出的是DOCUMENT_NODE类型
String li = liNode.getFirstChild().getNodeValue();
}
……
……

关于DOM将文本也视为一个结点这个我知道,所以在【2】的地方用getFirstChild().getNodeValue()才取到<patter>标签的文本值。
但是【1】【3】两处出现的问题我就很不理解了,为什么一会要加getNextSibling()一会又不加,而且感觉原理上不对啊?

请各位大虾多多指教。我查了很多资料了,但是没找到我这种情况的,我看别人的代码都挺正常的啊……
...全文
2364 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
kit_147 2008-11-08
  • 打赏
  • 举报
回复
的确是这个原因。
这代码本来是用C#写的,没有这个问题,看来是自己粗心了。
谢谢。
nelson_yzq 2008-11-08
  • 打赏
  • 举报
回复
根据你的XML文档,在DOM中,其实Template有三个直接子节点:1。 文本节点(回车换行空格等, 在<template> 和<random>之间);2。元素节点(random);3。文本节点(回车换行空格在</random>和</template>之间),所以template.getFirstChild()返回的是文本节点。你可以试试,如果对文档作以下改动, Template就没有直接文本节点了。
<template><random>
<li>你猜看 </li>
<li>长沙啊 </li>
<li>不告诉你 </li>
</random></template>
java__king 2008-11-07
  • 打赏
  • 举报
回复
up
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class ReadXML { public static void main(String[] args) { try { // 得到DOM解析器的工厂实例 DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance(); // 从DOM工厂获得DOM解析器 DocumentBuilder dombuilder = domfac.newDocumentBuilder(); // 把要解析XML文档转化为输入流,以便DOM解析解析它 InputStream is = new FileInputStream("test.xml"); // 解析XML文档的输入流,得到一个Document Document doc = dombuilder.parse(is); // 得到XML文档的根节点 Element root = doc.getDocumentElement(); // 得到节点的子节点 NodeList books = root.getChildNodes(); if (books != null) { // 轮循子节点 for (int i = 0; i < books.getLength(); i++) { // 获取book节点 Node book = books.item(i); if (book.getNodeType() == Node.ELEMENT_NODE) { // 取得节点的属性值 String email = book.getAttributes().getNamedItem( "email").getNodeValue(); System.out.println(email); // 轮循子节点 for (Node node = book.getFirstChild(); node != null; node = node.getNextSibling()) { if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getNodeName().equals("name")) { // 获得节点的文本值 String name = node.getFirstChild() .getNodeValue(); System.out.println(name); } if (node.getNodeName().equals("price")) { // 获得节点的文本值 String price = node.getFirstChild() .getNodeValue(); System.out.println(price); } } } } } } } // 异常处理 catch (ParserConfigurationException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧