【问题标题】:How to parse within CDATA in XML using Java如何使用 Java 在 XML 中的 CDATA 中进行解析
【发布时间】:2014-10-06 04:02:53
【问题描述】:

在搜索现有的 CDATA 讨论后,我发现没有一个能够实现我正在尝试的目标。

是否可以在标签不唯一的 CDATA 中进行解析?

下面是 XML 文档,我试图在下面的第 5 行检索具有多个感兴趣字段(即数据加载、质量、状态、索引)的 CDATA 块中的每个字段。每个字段在 CDATA 块中都用“li”标签标记(即使它是字符数据空间):

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Document>
 <name>area Area Date: 2014-07-31</name>
 <Placemark><name>P07L327</name><Point><coordinates>-96.26879,85.19125</coordinates></Point><description><![CDATA[<ol><li> Data Loaded:  NO</li><li>Quality: 5</li><li>Status: UP</li><li>Index: 72</li></eol>]]></description><Style> id = "colorIcon"</Style></Placemark>
 <coordinates>-96.26879,85.19125,0 -96.26879,85.19125,0 -96.26879,85.19125,0 -96.26879,85.19125,0 -96.26879,45.14698,0 </coordinates>
</Document>
</kml>

目前输出是这样的:

Name: <ol><li> Data Loaded:  NO</li><li>Quality: 5</li><li>Status: UP</li><li>Index: 72</li></eol>

在 CDATA 块中,我的意图是为每个字段输出一个新行以及相应的结果。

下面是到目前为止编写的代码,它给出了上面列出的当前输出:

    package com.lucy.seo;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.CharacterData;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.File;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;


public class ReadXMLFile {

public static void main(String[] args ) throws Exception {

File fXmlFile = new File("C:/XML_UltraEdit/XML_Sandbox/Oracle_Java_Project/Test_Doc.xml");
    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(fXmlFile);

doc.getDocumentElement().normalize();

System.out.println("Root element :" + doc.getDocumentElement().getNodeName());

NodeList nList = doc.getElementsByTagName("Placemark");

System.out.println("----------------------------");

for (int temp = 0; temp < nList.getLength(); temp++) {
    Element element = (Element) nList.item(temp);
            NodeList name = element.getElementsByTagName("description");
            Element line = (Element) name.item(0);
            System.out.println("Name: " + getCharacterDataFromElement(line));
    }
}
public static String getCharacterDataFromElement(Element f) {

         NodeList list = f.getChildNodes();
         String data;

         for(int index = 0; index < list.getLength(); index++){
             if(list.item(index) instanceof CharacterData){
                 CharacterData child  = (CharacterData) list.item(index);
                 data = child.getData();

                 if(data != null && data.trim().length() > 0)
                    return child.getData();
             }
         }
         return "";
}
}

感谢您对此的任何帮助! -- 谢谢!

2014 年 9 月 2 日更新

使用最终解决方案更新编辑。感谢所有在这里发布解决方案并提供帮助的人。由于库冲突,解决方案分为两段代码/文件:

//First file which is input to the second file followed afterwards

import java.io.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


public class ReadXMLFile {

public static void main(String[] args ) throws Exception {
PrintStream out = new PrintStream(new FileOutputStream("C:/XML_UltraEdit/XML_Sandbox/NetBeans_Java_Project/temp_file.html"));
System.setOut(out);
File fXmlFile = new File("C:/XML_UltraEdit/XML_Sandbox/NetBeans_Java_Project/raw_input.xml");
    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(fXmlFile);


//optional, but recommended
//read this - http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
doc.getDocumentElement().normalize();

NodeList nList = doc.getElementsByTagName("Placemark");

    //create a buffered reader that connects to the console, we use it so we can read lines
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    System.out.println("<html xlmns=http://www.w3.org/1999/xhtml>");

for (int temp = 0; temp < nList.getLength(); temp++) {
                Node nNode = nList.item(temp);
                Element eElement = (Element) nNode;

    Element element = (Element) nList.item(temp);
            NodeList name = element.getElementsByTagName("description");
            Element line = (Element) name.item(0);

            System.out.println("<bracket><li>Name: " + eElement.getElementsByTagName("name").item(0).getTextContent() + "</li>");
            System.out.println("<description>Description: " + getCharacterDataFromElement(line) + "</description></bracket>");
    }
    System.out.println("</html>");

//read a line from the console
String lineFromInput = in.readLine();

//output to the file a line
out.println(lineFromInput);                                 
out.close();    
}
public static String getCharacterDataFromElement(Element f) {

         NodeList list = f.getChildNodes();
         String data;

         for(int index = 0; index < list.getLength(); index++){
             if(list.item(index) instanceof CharacterData){
                 CharacterData child  = (CharacterData) list.item(index);
                 data = child.getData();

                 if(data != null && data.trim().length() > 0)
                    return child.getData();
             }
         }
         return "";
}
}


//Second File
package ReadXMLFile_part2;

import java.io.*;

import org.jsoup.Jsoup;
import org.jsoup.select.Elements;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ReadXMLFile_part2 {

public static void main(String[] args) throws Exception {

PrintStream out = new PrintStream(new FileOutputStream("C:/XML_UltraEdit/XML_Sandbox/NetBeans_Java_Project/PA-PTH013_Output_Meters.xml"));
System.setOut(out);

System.out.println("*** JSOUP ***");

File input = new File("C:/XML_UltraEdit/XML_Sandbox/NetBeans_Java_Project/temp_file.html");
Document doc = null;
    try {
        doc = Jsoup.parse(input,"UTF-8", "http://www.w3.org/1999/xhtml" );
    } catch (IOException ex) {
        Logger.getLogger(ReadXMLFile_part2.class.getName()).log(Level.SEVERE, null, ex);
    }
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

Elements brackets = doc.getElementsByTag("bracket");

for (Element bracket : brackets) {
    Elements lis = bracket.select("li");

        for (Element li : lis){
        System.out.println(li.text());
        }
    break;
}
System.out.println();

//read a line from the console
String lineFromInput = in.readLine();

//output to the file a line
out.println(lineFromInput);                                 
out.close();    
}

}

【问题讨论】:

  • 您可以为整个 CDATA 块编写一个处理程序,然后对其进行自己的解析,但CDATA 的全部意义在于它被定义为不应被解析的纯字符数据XML 阅读器 =)
  • 谢谢,但是我如何解析具有相同 XML 标记的文本作为 li 元素?我找到的最接近的是:[link] stackoverflow.com/questions/12889253/…
  • 您已经知道如何将该 CDATA 作为原始数据获取,因此诀窍是使用 second 解析器(然后是 HTML 解析器,而不是 XML 解析器)并运行您的通过那个 CDATA 字符串。
  • 谢谢,正如您所说,我最终使用了第二个解析器(使用 HTML)并且已经工作但遇到了另一个问题。我已经在另一个线程上发布了完整的问题:[link] (stackoverflow.com/questions/25491424/…)

标签: java xml parsing dom cdata


【解决方案1】:

CDATA 是 XML 解释引擎的标记,无论它们在开始和结束之间遇到什么,都应该被视为“纯”(原始)字符数据。

因此,在某种程度上,它就像解析器的转义字符(可以包含许多字符)。

因此,您将找不到将 CDATA 中的任何内容报告为 XML 的 XML 解析器,因为规范规定它必须将其报告为字符流。 (因此:它不能将其解释为 XML 流,这实际上很好,因为没有任何东西要求内容确实是 XML)。

无论如何,您的解析器和代码都在按预期工作。

但是,如果你碰巧知道某个 CDATA 实例的内容确实是一个有效的 XML 实例,那么你可以为这个精确的内容打开一个新的 Parser,并适当地处理它。

p>

因此您可以获得getCharacterDataFromElement(line) 调用的输出,将其提供给您的documentBuilder,并使用这个新的Documentinstance 来解析您的li 元素的内容。

【讨论】:

  • 谢谢,但我一直在处理 StackOverFlow 的大部分问题,但不确定如何解析具有相同 XML 标记的文本作为 li 元素。我找到的最接近的是这两个:[link] stackoverflow.com/questions/12889253/… [link] stackoverflow.com/questions/18391388/…
  • 当您在寻找placemark 时,您编写了一个“for”循环来查找“按(那个)标签名称的所有元素”。好吧,如果您正在寻找li,您也会这样做。不同之处在于 placemark 只匹配一次,而 li 会匹配多次。
【解决方案2】:

您的问题有些矛盾,因为 CDATA 是对解析器的显式指令,不解析它在 CDATA 中看到的内容。所以获取内容解析的最简单方法是首先不包含 CDATA 标记。

但是,在告诉解析器不要解析 CDATA 内容后,您可以将内容提取为文本,然后将文本提交给解析器作为第二次解析操作。

【讨论】:

  • 谢谢,但是如何解析具有相同 XML 标记的文本,即 li 元素?我找到的最接近的是:[link] stackoverflow.com/questions/12889253/…
  • 对不起,我不明白你的问题。
  • 如前所述将 CDATA 内容提取为文本后,如何提取具有相同标记名称(即
  • )的 XML 标记?该示例在上面第一个代码 sn-p 的第 5 行 - thks
猜你喜欢
相关资源
最近更新 更多
热门标签