簡體   English   中英

使用 SAX Parser 獲取特定的子節點

[英]Fetch a particular child node using SAX Parser

強調文字我有以下xml:

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
    <title>Game Analysis</title>
    <item>
        <title>Game</title>
        <description>ABC</description>
        <releaseDate>Sat, 21 Feb 2012 05:18:23 GMT</releaseDate>       
    </item>
    <item>
        <title>CoD</title>
        <description>XYZ</description>
        <releaseDate>Sat, 21 Feb 2011 05:18:23 GMT</releaseDate>            
    </item>
</channel>
</rss>

我必須解析這個 xml 並獲取“item”下的所有子節點,然后檢查它是否包含“releaseDate”節點。 如果不是,那么我必須拋出一個異常。

我也嘗試過使用 xpath 但它不起作用。

    XPathFactory xPathfactory = XPathFactory.newInstance();
    XPath xpath = xPathfactory.newXPath();
    XPathExpression expr = xpath.compile("//channel/item");

    Object result = expr.evaluate(document, XPathConstants.NODESET);
    NodeList nodes = (NodeList) result;
    for (int i = 0; i < nodes.getLength(); i++) {
        System.out.println(nodes.item(i).getChildNodes());
    }

試試這個代碼。 不要忘記在您的項目中包含 SAX 解析器庫並從 XML 文檔中刪除 rss-string(希望這被接受)。

public class SaxParserTest {
    public static void main(String... argv) {
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        try {
            SAXParser saxParser = saxParserFactory.newSAXParser();
            MyHandler handler = new MyHandler();
            saxParser.parse(new File("your path to XML-file here"), handler);
            List<Item> items = handler.getChannel().getItems();
            // your check of item release dates here
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class MyHandler extends DefaultHandler {
    private StringBuilder data = new StringBuilder();

    private Channel channel;

    private String itemTitle;
    private String itemDescription;
    private String itemReleaseDate;

    private boolean isItem;

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if (!qName.equals("rss")) {
            if (qName.equalsIgnoreCase("channel")) {
                channel = new Channel();
            } else if (qName.equalsIgnoreCase("item")) {
                isItem = true;
            }
            data.setLength(0);
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (qName.equalsIgnoreCase("title")) {
            if (!isItem) {
                channel.setTitle(data.toString());
            } else {
                itemTitle = data.toString();
            }
        } else if (qName.equalsIgnoreCase("item")) {
            channel.addItem(new Item(itemTitle, itemDescription, itemReleaseDate));
            itemTitle = null;
            itemDescription = null;
            itemReleaseDate = null;
            isItem = false;
        } else if (qName.equalsIgnoreCase("description")) {
            itemDescription = data.toString();
        } else if (qName.equalsIgnoreCase("releaseDate")) {
            itemReleaseDate = data.toString();
        }
    }

    @Override
    public void characters(char ch[], int start, int length) throws SAXException {
        data.append(new String(ch, start, length));
    }

    public Channel getChannel() {
        return channel;
    }
}

class Channel {
    private String title;
    private List<Item> items;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public List<Item> getItems() {
        return items;
    }

    public void setItems(List<Item> items) {
        this.items = items;
    }

    public void addItem(Item item) {
        if (items == null) {
            items = new ArrayList<Item>();
        }
        items.add(item);
    }
}

class Item {
    private String title;
    private String description;
    private String releaseDate;

    public Item(String title, String description, String releaseDate) {
        this.title = title;
        this.description = description;
        this.releaseDate = releaseDate;
    }
    public String getReleaseDate() {
        return releaseDate;
    }
}

XPath 應該可以正常工作,甚至可以用於創建更短的解決方案。 表達式//channel/item[not(releaseDate)]將返回所有沒有releaseDate子節點的item節點。 所以這段代碼應該會給你答案:

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);

    Document document = dbf
            .newDocumentBuilder()
            .parse(...);

    XPath xpath = XPathFactory
            .newInstance()
            .newXPath();

    NodeList list = (NodeList) xpath.evaluate("//channel/item[not(releaseDate)]", document, XPathConstants.NODESET);
    if (list.getLength() != 0) {
        throw new Exception("Found <item> without <releaseDate>");
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM