首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 使用 DOM 解析器提取 RSS Feed 中 description 標籤完整內容

     編輯:程式設計綜合問答

問題背景

RSS Feed 中 <description> 包含嵌套標籤(<image>、<text>、CDATA 等),SAX 解析器按事件流處理,難以一次性獲取完整內部 XML 片段。DOM 解析器將整個文檔加載為樹,便於直接提取子樹。

DOM 解析完整代碼


public List<String> parseDescriptions(InputStream inputStream) throws Exception {
    List<String> descriptions = new ArrayList<>();

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true); // 支援命名空間
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse(inputStream);

    // 獲取所有 <item> 節點
    NodeList items = doc.getElementsByTagName("item");
    for (int i = 0; i < items.getLength(); i++) {
        Element item = (Element) items.item(i);

        // 獲取第一個 <description> 子元素
        NodeList descNodes = item.getElementsByTagName("description");
        if (descNodes.getLength() > 0) {
            Element descElement = (Element) descNodes.item(0);

            // 方案 A:獲取文本內容(包含 CDATA 解碼後的純文本)
            String textContent = descElement.getTextContent();

            // 方案 B:獲取內部原始 XML(包含嵌套標籤結構)
            String innerXml = getInnerXml(descElement);

            descriptions.add(innerXml); // 或 textContent
        }
    }
    return descriptions;
}

// 輔助方法:將 Node 及其子樹序列化為 XML 字串
private String getInnerXml(Node node) {
    try {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        StringWriter writer = new StringWriter();
        // 僅輸出子節點,不包含自身標籤
        for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
            transformer.transform(new DOMSource(child), new StreamResult(writer));
        }
        return writer.toString();
    } catch (TransformerException e) {
        throw new RuntimeException(e);
    }
}

關鍵點說明

  1. DocumentBuilder.parse(InputStream) 直接解析流,無需先讀成字串。
  2. getElementsByTagName("description") 遞歸查找所有後代,若 description 只在 item 直屬,可用 item.getElementsByTagName("description")。
  3. getTextContent() 返回純文本(CDATA 已解碼、標籤移除);getInnerXml() 保留結構。
  4. 大文件(>1MB)DOM 佔用記憶體大,考慮使用 XmlPullParser 流式讀取至目標標籤再切換 DOM 解析該片段。

SAX 方案對比(若堅持用 SAX)


// 在 DefaultHandler 中
boolean inDescription = false;
StringBuilder descBuffer = new StringBuilder();

@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
    if ("description".equals(qName)) inDescription = true;
}

@Override
public void characters(char[] ch, int start, int length) {
    if (inDescription) descBuffer.append(ch, start, length);
}

@Override
public void endElement(String uri, String localName, String qName) {
    if ("description".equals(qName)) {
        inDescription = false;
        String fullDesc = descBuffer.toString(); // 含 CDATA 內容
        descBuffer.setLength(0);
    }
}

SAX 需手動維護狀態,處理嵌套標籤極其繁瑣,**強烈推薦 DOM 或 XmlPullParser**。

總結

RSS description 含豐富結構時,DOM 解析器配合 Transformer 序列化內部 XML 是最直接可靠的方法。大文件場景可混合使用 Pull 解析定位片段再 DOM 解析。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved