【问题标题】:How to parse XML for <![CDATA[]]>如何为 <![CDATA[]]> 解析 XML
【发布时间】:2012-01-19 07:44:38
【问题描述】:

如何解析包含在&lt;![CDATA[---]... 中的数据的XML 我们如何解析xml 并获取包含在CDATA 中的数据???

【问题讨论】:

  • 您是“手动”解析文件还是使用任何 XMLReader 类(以及哪个类)?

标签: java xml parsing cdata


【解决方案1】:
public static void main(String[] args) throws Exception {
  File file = new File("data.xml");
  DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
 //if you are using this code for blackberry xml parsing
  builder.setCoalescing(true);
  Document doc = builder.parse(file);

  NodeList nodes = doc.getElementsByTagName("topic");
  for (int i = 0; i < nodes.getLength(); i++) {
    Element element = (Element) nodes.item(i);
    NodeList title = element.getElementsByTagName("title");
    Element line = (Element) title.item(0);
    System.out.println("Title: " + getCharacterDataFromElement(line));
  }
}
public static String getCharacterDataFromElement(Element e) {
  Node child = e.getFirstChild();
  if (child instanceof CharacterData) {
    CharacterData cd = (CharacterData) child;
    return cd.getData();
  }
  return "";
}

(http://www.java2s.com/Code/Java/XML/GetcharacterdataCDATAfromxmldocument.htm)

【讨论】:

  • 我宁愿做这样的事情: if (child != null && (child instanceof CharacterData)) { return ((CharacterData) child).getData(); } else { 返回 e.getNodeValue();为了无缝处理 CDATA 块的存在/不存在。
  • 您能否提供一些文字来描述您在做什么以及为什么要使用DocumentBuilderFactory
  • 在当前的 Java DOM 实现中,您可以使用 e.getTextContent() 简单地以文本数据的形式访问 CDATA。 See example 没有类型检查,强制转换,e.getData()
【解决方案2】:

由于所有先前的答案都使用基于DOM 的方法。这是使用STAX 使用基于流的方法解析CDATA 的方法。

使用以下模式:

  switch (EventType) {
        case XMLStreamConstants.CHARACTERS:
        case XMLStreamConstants.CDATA:
            System.out.println(r.getText());
            break;
        default:
            break;
        }

完整示例:

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;

public void readCDATAFromXMLUsingStax() {
    String yourSampleFile = "/path/toYour/sample/file.xml";
    XMLStreamReader r = null;
    try (InputStream in =
            new BufferedInputStream(new FileInputStream(yourSampleFile));) {
        XMLInputFactory factory = XMLInputFactory.newInstance();
        r = factory.createXMLStreamReader(in);
        while (r.hasNext()) {
            switch (r.getEventType()) {
            case XMLStreamConstants.CHARACTERS:
            case XMLStreamConstants.CDATA:
                System.out.println(r.getText());
                break;
            default:
                break;
            }
            r.next();
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    } finally {
        if (r != null) {
            try {
                r.close();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}

使用 /path/toYour/sample/file.xml

 <data>
    <![CDATA[ Sat Nov 19 18:50:15 2016 (1672822)]]>
    <![CDATA[Sat, 19 Nov 2016 18:50:14 -0800 (PST)]]>
 </data>

给:

 Sat Nov 19 18:50:15 2016 (1672822)                             
 Sat, 19 Nov 2016 18:50:14 -0800 (PST)       

【讨论】:

    【解决方案3】:

    CDATA 只是表示不应转义包含的数据。因此,只需获取标签文本。 XML 解析器应该返回没有CDATA 的清晰数据。

    【讨论】:

    • 获取文本数据:e.getTextContent();
    【解决方案4】:

    这里r.get().getResponseBody()是响应正文

    Document doc = getDomElement(r.get().getResponseBody());            
        NodeList nodes = doc.getElementsByTagName("Title");
        for (int i = 0; i < nodes.getLength(); i++) {
        Element element = (Element) nodes.item(i);
        NodeList title = element.getElementsByTagName("Child tag where cdata present");
        Element line = (Element) title.item(0);
        System.out.println("Title: "+ getCharacterDataFromElement(line));
    
    
        public static Document getDomElement(String xml) {
            Document doc = null;
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setCoalescing(true);
            dbf.setNamespaceAware(true);
            try {
                DocumentBuilder db = dbf.newDocumentBuilder();
                InputSource is = new InputSource();
                is.setCharacterStream(new StringReader(xml));
                doc = db.parse(is);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return doc;
        }
    
        public static String getCharacterDataFromElement(Element e) {
            Node child = e.getFirstChild();
            if (child instanceof CharacterData) {
                CharacterData cd = (CharacterData) child;
                return cd.getData();
            }
            return "";
        }
    

    【讨论】:

      【解决方案5】:

      以下是示例 XML 文件和用于检索嵌入在主 xml 中的 CDATA 中的 XML 的代码。

      <envelope>
       <Header>
        <id>123</id>
        <name>abc</name>
       </Header>
       <payload>
        <![CDATA[<?xml> <Document><validXML></validXML></Document>]]>
      </payload>
      </envelope>
      

      获取上述示例中给出的 CDATA XML 的 Xpath 将是

      /envelope/payload/text()
      

      因此,一旦您拥有上述 xml 的根文档,使用给定的路径,您就可以获取嵌入在 CDATA 中的 xml。

      下面是相同的实用方法。

      public String getSubDocument(Document rootDocument, String xPathString) throws Exception {
      XPath xPath = XPathFactory.newInstance().newXPath();
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = factory.newDocumentBuilder();
      Document rootDoc = builder.newDocument();
      String xmlString = (String)xPath.compile(xPathString).evaluate(rootDocument, XPathConstants.String);
      return xmlString;
      }
      

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-15
        • 1970-01-01
        • 2012-09-11
        • 1970-01-01
        • 2011-01-09
        • 2011-07-06
        相关资源
        最近更新 更多