2011-03-14 61 views
2

所以我必須編寫一個「重複檢查器」來比較兩個XML並查看它們是否相同(包含相同的數據)。現在,因爲它們來自同一個類並且從XSD生成,所以結構中的元素順序很可能是相同的。Python ElementTree重複檢查器

我可以考慮做重複檢查的最佳方式是設置兩個字典(dictLeft,dictRight)並將xpath#值保存爲密鑰和發生次數。事情是這樣的:

左:

{ 'my/path/to/name#greg': 1, 'my/path/to/name#john': 2, 'my/path/to/car#toyota': 1} 

{ 'my/path/to/name#greg': 1, 'my/path/to/name#bill': 1, 'my/path/to/car#toyota': 1} 

這兩個字典比較會給我的這兩個個XML是否是相同或不相當準確的指示(有是我可能得到錯誤結果的奇怪機會,但它非常遙遠)。

其他人有更好的主意嗎?也許ElementTree中我不知道的一個函數?

編輯:爲了更好地解釋:

<root><person><name>Bob</name><surname>marley</surname></root> 

<root><person><surname>marley</surname><name>Bob</name></root> 

將被視爲相同。我忽略了屬性。這個想法是保持代碼儘可能簡單,同時不會太多地影響性能。

+0

你能更好地定義這個問題嗎?你對「相同」的定義是什麼?子元素可以以任意順序嗎?可以將不同的子元素嵌套視爲相同嗎?屬性是否重要等等。另外,您的目標是什麼?性能?正確性?代碼簡單? – marr75 2011-03-14 15:44:16

+0

「相同」意味着包含的數據是相同的,不一定是順序。我忽略了屬性。 – Andre 2011-03-15 11:23:27

回答

1

OK,所以我不得不做出決定,並就與此:

foreach path in xpathlist 
    find entries for path for both xml1 and xml2 
    foreach entry in xmlentries1 
    dict1[path#entry.value]++ 
    foreach entry in xmlentries2 
    dict2[path#entry.value]++ 

    if dict1 and dict2 are not equal 
    return false 
return true 

我希望這是有道理的。這使我可以測試特定/所有xpath。如果有人有更好的算法,我都耳朵:)

0

從你的例子看來,你應該能夠使用iterparse並使用collections.Counter來計數每個標籤及其屬性的外觀作爲計數器的關鍵字。 例子:

from xml.etree import cElementTree as ElementTree 
from collections import Counter 

your_xml = get_xml() 
count = Counter() 
parser = ElementTree.iterparse(your_xml) 
for event, element in parser: 
    #joining string as key for ease of debugging, strictly speaking, 
    #one could use a tuple and save the str() on the attrib dict 
    key = "".join((element.tag, str(element.attrib), element.text)) 
    count[element.tag] += 1 

另外,您算正常的字典,只是比較這兩種類型的字典平等(概念比較簡單對我來說)。

+0

順便說一句,使用cElementTree和iterparse是,從我解析API響應和收集BigData的經驗,最好的表現,同時最容易維護python解決方案。我通常會創建一個字典映射標籤來調用標籤來解析每個標籤,這裏並不是真的必要(每個標籤都可以被處理),但是如果你想用xml來做更多的事情,這是一個非常強大的方法。 – marr75 2011-03-14 16:03:41

+0

能用iterparse解析一個Xpath嗎? – Andre 2011-03-15 11:33:32

+0

種。您將對您感興趣的標籤的子元素擁有Xpath支持,當您擁有所需的所有內容時,您可以將其破解。我不明白爲什麼要使用XML查詢語言Xpath來比較2個完整的xml文檔,這類似於比較兩個完整的sql表,通過查詢和比較一次行的子集或甚至單個行的子集。 – marr75 2011-03-16 21:14:30

0

如果兩個XML從相同的代碼生成並且包含相同的值(以相同的順序),那麼您可以簡單地對XML數據進行字符串比較。

如果可行,那麼它可能是簡單的解決方案,但可能有原因,爲什麼不適合你。

+0

是的,我想過這個問題,但問題是這些XML中的一些可能超過20000行。此外,嵌套項目的順序並不總是相同的順序。 – Andre 2011-03-15 11:31:11

0

此問題始於定義「相同」的含義。

例如,平等的一個簡單的定義,XML元素,是兩個XML元素是相等的,如果:

  • 他們在同一個命名空間,
  • 他們有相同的標籤名,
  • 它們具有相同的一組屬性,具有相同的值,它們各自的子節點列表(不包括註釋和處理指令)以及僅包含空白的文本節點以相同的順序包含相同的值。

有各種各樣的原因,這微不足道的定義可能不足以:

  • 可能要忽略不在你知道命名空間的元素 - 即你不希望你的應用程序如果其他應用程序正在將數據存儲在XML中,則平等測試失敗
  • 子元素排序可能不重要或(更糟糕)可能對某些元素而非其他元素有意義
  • 註釋,處理指令和僅空白文本節點可能是重要的
  • 您可能需要將空白標準化(見XSLT的normalize-space()功能)文本節點比較它們

一旦你定義平等,實現的方法來測試它是相對簡單了。但是你需要首先定義平等。