2017-03-23 5 views
1

Die Groovy documentation in der Verarbeitung XML-Abschnitt erwähnt, dass breadthFirst() ist auch auf die kürzere Syntax von *. Allerdings endet die * Nutzung eine Ebene unter dem übergeordneten Knoten nur bis durchlaufen:Groovy - XML ​​Baum Traversal BreiteFirst() Methode mit * als syntaktischen Zucker

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 

während breadthFirst() explizit mit tut, was erwarte ich, beides zu tun, welche Breiten ersten Traversal zu tun ist:

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 

* Semantik ist deutlich anders als breadthFirst(). Ist das erwartetes Verhalten oder habe ich etwas im doc verloren?

Antwort

1

Ich denke, die Dokumentation betont nicht, dass * ist eigentlich eine Kurzschrift, die nur die direkten Kinder des Knotens, bei dem es aufgerufen wird. Das Beispiel aus der Dokumentation zum Zeitpunkt des Schreibens dieses Artikels ist:

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

Beachten Sie, dass sie nicht response.'*' verwendet haben, wie Sie in Ihrem eigenen Beispiel tun. Also * ist nicht wirklich eine Abkürzung für breadthFirst() (ich stimme zu, die Dokumente sollten überprüft werden). Es bedeutet nur die direkten Kinder, während breadthFirst() die Knoten rekursiv durchläuft. Dies kann aus den Javadocs GPathResult.getProperty bestätigt werden:

Gibt die angegebene Eigenschaft dieses GPathResult zurück. Verwirklicht die folgen Abkürzungen:

  • '..' für parent()
  • '*' für children()
  • '**' für depthFirst()
  • '@' für Attribut Zugang

I erstellt this pull request, um es zu beheben.