2011-09-03 95 views
4

场景:XML文本提取

考虑下面的XML文件:

<a:root 
xmlns:h="http://www.w3.org/TR/html4/" 
xmlns:f="http://www.w3schools.com/furniture"> 

<h:table> 
    <h:tr> 
    <h:td>Apples</h:td> 
    <h:td>Bananas</h:td> 
    </h:tr> 
</h:table> 

<f:table> 
    <f:name>African Coffee Table</f:name> 
    <f:width>80</f:width> 
    <f:length>120</f:length> 
</f:table> 

aaaaaaaaaaaaaa 

</a:root> 

我如何提取的主要元素<a:root>中的文本:

"\naaaaaaaaaaaaaa\n" 

我的代码现在是:

import java.io.File; 
import java.util.Stack; 

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 

import org.w3c.dom.Document; 
import org.w3c.dom.NodeList; 


public class Proof { 
    public static void main(String[] args) { 
     Document doc = null; 
     DocumentBuilderFactory dbf = null; 
     DocumentBuilder docBuild = null; 
     try { 

      dbf = DocumentBuilderFactory.newInstance(); 
      docBuild = dbf.newDocumentBuilder(); 
      doc = docBuild.parse(new File("test2.xml")); 

      System.out.println(doc.getFirstChild().getTextContent()); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

但它返回我想要的文本(“aaaaaaaaaaaaaa”)+其余元素的内部文本。输出:

Apples 
    Bananas 




    African Coffee Table 
    80 
    120 


aaaaaaaaaaaaaa 

的要求是不使用额外的XML的Java库!

+0

好问题,+1。请参阅我的答案,以获取正确,简短且简单的XPath单行表达式,以便精确选择想要的文本节点。 :) –

+1

@Dimitre Novatchev,我认为你需要降低自我重要性。此时我无法提供Java代码,但我提供了C#代码,据我所知,您不仅仅是XML专家,还有.NET专家;-),因此您可以检查结果:var result = doc .SelectNodes(@“a:root/text()”,xmlnsManager).OfType ();'。结果应该是'\ r \ n \ r \ n \ r \ n' ...- :-) –

+0

@Kirill Polishchuk:用Saxon或AltovaXML运行您的代码并计算文本节点的数量 - 您的代码生成 - - 通过纯粹的运气 - 只有使用某些(微软)XSLT处理器的预期结果,因为它们的默认设置是剥离只包含空白的文本节点。这里我们不是讲“自重”,而是讲基础知识(缺乏)。 –

回答

3

通过@Kirill舒克答案是不corect

提议:

a:root/text() 
  1. 是一个相对表达并且如果未评价它具有根(/)节点作为上下文节点,它选择没有提供的XML文档英寸

  2. 即使XPath表达式:/a:root/text()是不正确,因为它选择三个文本节点 - 顶级元素的所有文本子节点 - 其中包括两个空格,只有文本节点。

这里是一个正确的XPath溶液

/a:root/text()[string-length(normalize-space()) > 0] 

当该XPath表达式所提供的XML文档施加(校正为良好的形成):

<a:root 
xmlns:a="UNDEFINED !!!!" 
xmlns:h="http://www.w3.org/TR/html4/" 
xmlns:f="http://www.w3schools.com/furniture"> 

<h:table> 
    <h:tr> 
    <h:td>Apples</h:td> 
    <h:td>Bananas</h:td> 
    </h:tr> 
</h:table> 

<f:table> 
    <f:name>African Coffee Table</f:name> 
    <f:width>80</f:width> 
    <f:length>120</f:length> 
</f:table> 

aaaaaaaaaaaaaa 

</a:root> 

它根据需要选择顶层元素的最后(也是唯一的非空白)文本节点子元素:

aaaaaaaaaaaaaa 

基于XSLT的验证

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:a="UNDEFINED !!!!" 
> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:text>"</xsl:text> 
    <xsl:copy-of select= 
    "/a:root/text() 
      [string-length(normalize-space()) > 0]"/>" 

</xsl:template> 
</xsl:stylesheet> 

当该变换是针对所提供的XML文档(以上),施加有用,正确selecte文本节点输出

" 

aaaaaaaaaaaaaa 

" 
+0

矫枉过正。 'a:root/text()'将精确选择1个文本节点(2个只包含空白的文本节点将被删除)。 –

2

您可以使用XPath:a:root/text()

+0

+1 - 使用Java SE 5及更高版本中的javax.xml.xpath API。 –

+0

这个XPath表达式至少有两个问题阻止它完全选择OP所需的文本节点 - 请参阅我的答案以获取更多详细信息。 –

2

使用此

import java.io.File; 
import java.util.Stack; 

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 

import org.w3c.dom.Document; 
import org.w3c.dom.NodeList; 


public class Proof { 
public static void main(String[] args) { 
    Document doc = null; 
    DocumentBuilderFactory dbf = null; 
    DocumentBuilder docBuild = null; 
    try { 

     dbf = DocumentBuilderFactory.newInstance(); 
     docBuild = dbf.newDocumentBuilder(); 
     doc = docBuild.parse(new File("test2.xml")); 

     Element x= doc.getDocumentElement(); 
     NodeList m=x.getChildNodes(); 
     for(int i=0;i<m.getLength();i++){ 
      Node it=m.item(i); 
      if(it.getNodeType()==3){ 
       System.out.println(it.getNodeValue()); 
      } 
     } 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 
} 

}