2012-07-03 37 views
3

所以我有一個項目,我需要拉一個每5分鐘更新一次的XML文件。不過,我正在設計我的程序,以便在每次更新時都拉取此文件。Java:從XML文件讀取最後一個條目

的XML文件的數據結構是這樣的......

<m:REPORT_DATA> 
    <m:DATA_ITEM>ENC</m:DATA_ITEM> 
    <m:RESOURCE_NAME>DLAP</m:RESOURCE_NAME> 
    <m:OPR_DATE>2012-06-02</m:OPR_DATE> 
    <m:INTERVAL_NUM>1</m:INTERVAL_NUM> 
    <m:VALUE>16.77734</m:VALUE> 
</m:REPORT_DATA> 
<m:REPORT_DATA> 
    <m:DATA_ITEM>ENC</m:DATA_ITEM> 
    <m:RESOURCE_NAME>DLAP</m:RESOURCE_NAME> 
    <m:DATE>2012-06-02</m:OPR_DATE> 
    <m:INTERVAL_NUM>2</m:INTERVAL_NUM> 
    <m:VALUE>16.77739</m:VALUE> 
</m:REPORT_DATA> 
.... 

假設那天我把它的第200位的時候,我怎麼會搶剛剛過去的值

"<m:VALUE>16.77739</m:VALUE>" 

並獲得我的數據庫的價值?

我撕裂有關使用薩克斯,XPATH或DOM。一些幫助會很棒。

+0

多大的文件? – Dave

+0

你有沒有考慮過使用任何正則表達式? – BlackVegetable

+0

該文件是大致275K,這是未壓縮記錄288上的5分或6的動作。 –

回答

4

如果你有一個根,可以說<m:REPORTS>,發現使用XPath的最後一個值是相當簡單:

XPathFactory f = XPathFactory.newInstance() ; 
    XPath x = f.newXPath() ; 
    try { 
     InputSource source = new InputSource(new FileInputStream("logfile.xml")) ; 
     XPathExpression expr = x.compile("//REPORT_DATA[DATA_ITEM='ENC'][last()]/VALUE/text()") ; 
     String s = expr.evaluate(source) ; 
     System.out.println("Last value: " + s) ; 
    } 
    catch(Throwable t) { 
     System.err.println("Error: " + t) ; 
    } 
+0

如果數據項= ENC&report_data [last()]/VALUE仍然存在,是否有某種方法可以做到這一點? –

+0

我不確定我完全理解了您的評論,但我更新了代碼以搜索具有DATA_ITEM作爲「ENC」的最後一個REPORT_DATA。 – mazaneicha

0

這不是它不能很好地形成的「XML文件」在這個意義上,因爲它不具有根元素(或它具有多個根元素)。因此它不能直接由XML庫加載,所以不能使用DOM,XPath或XSLT。

您是使用過一些簡單的模式匹配檢測每個段的起點,找到最後一段,然後只有段裝入用於提取DOM更好。

+0

你是正確的,這是不正確的XML,但它會很簡單,添加頂級標籤到他的輸入流。所以,我認爲這不排除使用xml技術。 –

+0

它的確如此,我只是認爲包含它們並不重要,因爲我說這是正常的xml。 <?xml version =「1.0」encoding =「UTF-8」?> 還有50多行標題,當我告訴你這個XML是兼容的,格式良好的,並由一個代理商處理的,這使得它能夠適應我嘗試過的任何方式。我的主要問題是如何篩選ENC類型的數據項,它是最後一個值。 –

+1

爲什麼要解析整個日誌文件,可能是幾百兆字節,只是爲了處理最後一個條目?這可能最終會變得非常浪費。 –

4

這不是一個良好的XML, 您可以使用XPath找到最後一個節點,例如 // REPORT_DATA [位置()=最後()] 返回最後REPORT_DATA節點 以及用於使用讀取XML的xpath看到How to read XML using XPath in Java

// REPORT_DATA [最後一個()]/DATA_ITEM [文本()=」 ENC「]

,這將返回節點,它的DATA_ITEM等於 「ENC」

或// REPORT_DATA [最後()]/VALUE [文本()= 「ENC」]

0

使用SAX。

用XPath或DOM,你必須建立一個DOM緩慢且昂貴的內存,尤其是1個查找。

SAX是快,但會要求你保持跟蹤你的位置和狀態,而你的情況應該是很容易的。只需查找您的REPORT_DATA元素,收集其封裝的數據,並且如果它是最後一個(到達最終文檔),您就可以獲得輸出。

0

如果你能行給定數目的計算,或者如果有一個上限,你可以指望得到的最後一個元素的行數,你可以寫一個腳本來尾部最後N行,並有你的程序調用腳本。

0
//filePath the path to the file you want to parse, tag the tag of the node you want to search.  
public static String getLastNode(String filePath, String tag) throws    ParserConfigurationException, SAXException, IOException{ 
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    DocumentBuilder builder = factory.newDocumentBuilder(); 
    Document doc = docBuilder.parse(filePath); 

    return doc.getElementsByTagName(tag).item(doc.getElementsByTagName(tag).getLength()-1).getTextContent(); 
//if you don't care about specific tag name just use : 
//return doc.getLastChild().getTextContent; 


}