2009-04-21 43 views
35

Tôi không thể tìm nạp giá trị văn bản bằng Node.getNodeValue(), Node.getFirstChild().getNodeValue() hoặc với Node.getTextContent().Nhận giá trị văn bản Nút XML với Java DOM

XML của tôi là như

<add job="351"> 
    <tag>foobar</tag> 
    <tag>foobar2</tag> 
</add> 

Và tôi đang cố gắng để có được thẻ giá trị (yếu tố phi văn bản lấy tác phẩm tốt). mã Java của tôi có vẻ như

Document doc = db.parse(new File(args[0])); 
Node n = doc.getFirstChild(); 
NodeList nl = n.getChildNodes(); 
Node an,an2; 

for (int i=0; i < nl.getLength(); i++) { 
    an = nl.item(i); 

    if(an.getNodeType()==Node.ELEMENT_NODE) { 
     NodeList nl2 = an.getChildNodes(); 

     for(int i2=0; i2<nl2.getLength(); i2++) { 
      an2 = nl2.item(i2); 

      // DEBUG PRINTS 
      System.out.println(an2.getNodeName() + ": type (" + an2.getNodeType() + "):"); 

      if(an2.hasChildNodes()) 
       System.out.println(an2.getFirstChild().getTextContent()); 

      if(an2.hasChildNodes()) 
       System.out.println(an2.getFirstChild().getNodeValue()); 

      System.out.println(an2.getTextContent()); 
      System.out.println(an2.getNodeValue()); 
     } 
    } 
} 

Nó in ra

tag type (1): 
tag1 
tag1 
tag1 
null 
#text type (3): 
_blank line_ 
_blank line_ 
... 

Thanks for the help.

+1

Sẽ giúp ích nếu bạn chỉ rõ rõ biến 'n' hiện đang nắm giữ chính xác, Tài liệu hoặc tài liệuElement? – AnthonyWJones

+1

Tôi đã thêm phần khai báo 'n' – Emilio

Trả lời

45

Tôi cũng sẽ in kết quả của an2.getNodeName() cho mục đích gỡ lỗi. Tôi đoán là mã thu thập thông tin cây của bạn không thu thập thông tin đến các nút mà bạn cho là. Nghi ngờ đó được tăng cường bởi việc thiếu kiểm tra các tên node trong mã của bạn.

Ngoài ra, javadoc cho Nút xác định "getNodeValue()" để trả về giá trị rỗng cho các nút của phần tử loại. Vì vậy, bạn thực sự nên sử dụng getTextContent(). Tôi không chắc tại sao điều đó không cho bạn văn bản mà bạn muốn.

Có thể lặp lại con của nút thẻ của bạn và xem loại nào?

thử mã này và nó làm việc cho tôi:

String xml = "<add job=\"351\">\n" + 
      " <tag>foobar</tag>\n" + 
      " <tag>foobar2</tag>\n" + 
      "</add>"; 
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
DocumentBuilder db = dbf.newDocumentBuilder(); 
ByteArrayInputStream bis = new ByteArrayInputStream(xml.getBytes()); 
Document doc = db.parse(bis); 
Node n = doc.getFirstChild(); 
NodeList nl = n.getChildNodes(); 
Node an,an2; 

for (int i=0; i < nl.getLength(); i++) { 
    an = nl.item(i); 
    if(an.getNodeType()==Node.ELEMENT_NODE) { 
     NodeList nl2 = an.getChildNodes(); 

     for(int i2=0; i2<nl2.getLength(); i2++) { 
      an2 = nl2.item(i2); 
      // DEBUG PRINTS 
      System.out.println(an2.getNodeName() + ": type (" + an2.getNodeType() + "):"); 
      if(an2.hasChildNodes()) System.out.println(an2.getFirstChild().getTextContent()); 
      if(an2.hasChildNodes()) System.out.println(an2.getFirstChild().getNodeValue()); 
      System.out.println(an2.getTextContent()); 
      System.out.println(an2.getNodeValue()); 
     } 
    } 
} 

Output:

#text: type (3): foobar foobar 
#text: type (3): foobar2 foobar2 
+1

bây giờ tôi cũng đang in .getNodeName() .. và nó trả về giá trị đúng (thẻ) – Emilio

+0

Phần tử thẻ của tôi không có con:/Nếu tôi thử đơn giản với an2. getFirstChild(). getTextContent() hoặc tương tự nó ném một NullPointerException – Emilio

+0

Thử sử dụng getChildElements thay vì getFirstChild(). Có lẽ getFirstChild() đang bỏ qua các nút gõ Element vì lý do nào đó? – jsight

17

Nếu XML của bạn đi khá sâu, bạn có thể muốn xem xét sử dụng XPath, mà đi kèm với JRE của bạn , để bạn có thể truy cập nội dung dễ dàng hơn bằng cách sử dụng:

String text = xp.evaluate("//add[@job='351']/tag[position()=1]/text()", 
    document.getDocumentElement()); 

Ví dụ đầy đủ:

import static org.junit.Assert.assertEquals; 
import java.io.StringReader;  
import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.xpath.XPath; 
import javax.xml.xpath.XPathFactory;  
import org.junit.Before; 
import org.junit.Test; 
import org.w3c.dom.Document; 
import org.xml.sax.InputSource; 

public class XPathTest { 

    private Document document; 

    @Before 
    public void setup() throws Exception { 
     String xml = "<add job=\"351\"><tag>foobar</tag><tag>foobar2</tag></add>"; 
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder db = dbf.newDocumentBuilder(); 
     document = db.parse(new InputSource(new StringReader(xml))); 
    } 

    @Test 
    public void testXPath() throws Exception { 
     XPathFactory xpf = XPathFactory.newInstance(); 
     XPath xp = xpf.newXPath(); 
     String text = xp.evaluate("//add[@job='351']/tag[position()=1]/text()", 
       document.getDocumentElement()); 
     assertEquals("foobar", text); 
    } 
} 
+0

Thật không may là một công việc giáo dục và tôi phải sử dụng DOM apis:/ – Emilio

+0

Bạn có thể sử dụng API JDOM không? Việc làm việc dễ dàng hơn nhiều. – jdigital

+0

Cảm ơn, ví dụ hoàn chỉnh này (với hàng nhập khẩu) thực sự đã giúp tôi sau khi đấu tranh với các giải pháp tương tự khác. –

1

Tôi sử dụng một java rất cũ. Jdk 1.4.08 và tôi có cùng một vấn đề. Lớp Node cho tôi không có phương thức getTextContent(). Tôi đã phải sử dụng Node.getFirstChild().getNodeValue() thay vì Node.getNodeValue() để nhận giá trị của nút. Điều này cố định cho tôi.

1

Nếu bạn đang mở để vtd-xml, vượt trội ở cả hai performance and memory efficiency, bên dưới là mã để làm những gì bạn đang tìm kiếm ... trong cả XPath và điều hướng thủ công ... mã tổng thể ngắn gọn và dễ hiểu hơn ...

import com.ximpleware.*; 
public class queryText { 
    public static void main(String[] s) throws VTDException{ 
     VTDGen vg = new VTDGen(); 
     if (!vg.parseFile("input.xml", true)) 
      return; 
     VTDNav vn = vg.getNav(); 
     AutoPilot ap = new AutoPilot(vn); 
     // first manually navigate 
     if(vn.toElement(VTDNav.FC,"tag")){ 
      int i= vn.getText(); 
      if (i!=-1){ 
       System.out.println("text ===>"+vn.toString(i)); 
      } 
      if (vn.toElement(VTDNav.NS,"tag")){ 
       i=vn.getText(); 
       System.out.println("text ===>"+vn.toString(i)); 
      } 
     } 

     // second version use XPath 
     ap.selectXPath("/add/tag/text()"); 
     int i=0; 
     while((i=ap.evalXPath())!= -1){ 
      System.out.println("text node ====>"+vn.toString(i)); 
     } 
    } 
} 
Các vấn đề liên quan