2017-03-23 20 views
1

處理XML部分中的Groovy documentation提到breadthFirst()*的較短語法是同義的。然而,*使用最終只遍歷父節點下一層:Groovy-XML Tree Traversal使用*作爲語法糖的breadthFirst()方法

def books = '''\ 
<response> 
    <books> 
     <book available="20" id="1"> 
     <title>foo</title> 
     <author id="1">foo author</author> 
     </book> 
     <book available="14" id="2"> 
     <title>bar</title> 
     <author id="2">bar author</author> 
     </book> 
    </books> 
</response>''' 

def response = new XmlSlurper().parseText(books) 
def bk = response.'*'.find { node -> 
    node.name() == 'book' && node['@id'].toInteger() == 2 
} 
assert bk.empty 

而使用breadthFirst()明確做什麼,我都期盼做這做廣度優先遍歷:

def books = '''\ 
<response> 
    <books> 
     <book available="20" id="1"> 
     <title>foo</title> 
     <author id="1">foo author</author> 
     </book> 
     <book available="14" id="2"> 
     <title>bar</title> 
     <author id="2">bar author</author> 
     </book> 
    </books> 
</response>''' 

def response = new XmlSlurper().parseText(books) 
def bk = response.breadthFirst().find { node -> 
    node.name() == 'book' && node['@id'].toInteger() == 2 
} 
assert bk.title == 'bar' // bk is no longer an empty list of children 

*語義明顯不同於breadthFirst()。這是預期的行爲,還是我錯過了文檔中的某些內容?

回答

1

我認爲這個文檔並沒有強調*實際上是一個簡寫,它只能得到直接被調用的節點的子節點。從在寫這篇文章的時候文檔的例子是:作爲你在自己的例子一樣,他們沒有使用response.'*'

def catcherInTheRye = response.value.books.'*'.find { node-> 
/* [email protected] == 2 could be expressed as node['@id'] == 2 */ 
    node.name() == 'book' && [email protected] == '2' 
} 

通知。所以*並非真的是breadthFirst()(我同意文檔應審查)的簡寫。它僅僅意味着直接的孩子,而breadthFirst()遞歸地遍歷節點。這可以從GPathResult.getProperty的Javadocs確認:

返回此GPathResult的指定屬性。 。實現如下快捷鍵:

  • '..'parent()
  • '*'children()
  • '**'depthFirst()
  • '@'的屬性訪問

我創建this pull request來解決它。