1xmlquery 2==== 3[![Build Status](https://travis-ci.org/antchfx/xmlquery.svg?branch=master)](https://travis-ci.org/antchfx/xmlquery) 4[![Coverage Status](https://coveralls.io/repos/github/antchfx/xmlquery/badge.svg?branch=master)](https://coveralls.io/github/antchfx/xmlquery?branch=master) 5[![GoDoc](https://godoc.org/github.com/antchfx/xmlquery?status.svg)](https://godoc.org/github.com/antchfx/xmlquery) 6[![Go Report Card](https://goreportcard.com/badge/github.com/antchfx/xmlquery)](https://goreportcard.com/report/github.com/antchfx/xmlquery) 7 8Overview 9=== 10 11`xmlquery` is an XPath query package for XML documents, allowing you to extract 12data or evaluate from XML documents with an XPath expression. 13 14`xmlquery` has a built-in query object caching feature that caches recently used 15XPATH query strings. Enabling caching can avoid recompile XPath expression for 16each query. 17 18Change Logs 19=== 20 212020-08-?? 22- Add XML stream loading and parsing support. 23 242019-11-11 25- Add XPath query caching. 26 272019-10-05 28- Add new methods compatible with invalid XPath expression error: `QueryAll` and `Query`. 29- Add `QuerySelector` and `QuerySelectorAll` methods, support for reused query objects. 30- PR [#12](https://github.com/antchfx/xmlquery/pull/12) (Thanks @FrancescoIlario) 31- PR [#11](https://github.com/antchfx/xmlquery/pull/11) (Thanks @gjvnq) 32 332018-12-23 34- Added XML output including comment nodes. [#9](https://github.com/antchfx/xmlquery/issues/9) 35 362018-12-03 37- Added support to attribute name with namespace prefix and XML output. [#6](https://github.com/antchfx/xmlquery/issues/6) 38 39Installation 40==== 41``` 42 $ go get github.com/antchfx/xmlquery 43``` 44 45Getting Started 46=== 47 48### Find specified XPath query. 49 50```go 51list, err := xmlquery.QueryAll(doc, "a") 52if err != nil { 53 panic(err) 54} 55``` 56 57#### Parse an XML from URL. 58 59```go 60doc, err := xmlquery.LoadURL("http://www.example.com/sitemap.xml") 61``` 62 63#### Parse an XML from string. 64 65```go 66s := `<?xml version="1.0" encoding="utf-8"?><rss version="2.0"></rss>` 67doc, err := xmlquery.Parse(strings.NewReader(s)) 68``` 69 70#### Parse an XML from io.Reader. 71 72```go 73f, err := os.Open("../books.xml") 74doc, err := xmlquery.Parse(f) 75``` 76 77#### Parse an XML in a stream fashion (simple case without elements filtering). 78 79```go 80f, err := os.Open("../books.xml") 81p, err := xmlquery.CreateStreamParser(f, "/bookstore/book") 82for { 83 n, err := p.Read() 84 if err == io.EOF { 85 break 86 } 87 if err != nil { 88 ... 89 } 90} 91``` 92 93#### Parse an XML in a stream fashion (simple case advanced element filtering). 94 95```go 96f, err := os.Open("../books.xml") 97p, err := xmlquery.CreateStreamParser(f, "/bookstore/book", "/bookstore/book[price>=10]") 98for { 99 n, err := p.Read() 100 if err == io.EOF { 101 break 102 } 103 if err != nil { 104 ... 105 } 106} 107``` 108 109#### Find authors of all books in the bookstore. 110 111```go 112list := xmlquery.Find(doc, "//book//author") 113// or 114list := xmlquery.Find(doc, "//author") 115``` 116 117#### Find the second book. 118 119```go 120book := xmlquery.FindOne(doc, "//book[2]") 121``` 122 123#### Find all book elements and only get `id` attribute. (New Feature) 124 125```go 126list := xmlquery.Find(doc,"//book/@id") 127``` 128 129#### Find all books with id `bk104`. 130 131```go 132list := xmlquery.Find(doc, "//book[@id='bk104']") 133``` 134 135#### Find all books with price less than 5. 136 137```go 138list := xmlquery.Find(doc, "//book[price<5]") 139``` 140 141#### Evaluate total price of all books. 142 143```go 144expr, err := xpath.Compile("sum(//book/price)") 145price := expr.Evaluate(xmlquery.CreateXPathNavigator(doc)).(float64) 146fmt.Printf("total price: %f\n", price) 147``` 148 149#### Evaluate number of all book elements. 150 151```go 152expr, err := xpath.Compile("count(//book)") 153price := expr.Evaluate(xmlquery.CreateXPathNavigator(doc)).(float64) 154``` 155 156FAQ 157==== 158 159#### `Find()` vs `QueryAll()`, which is better? 160 161`Find` and `QueryAll` both do the same thing: searches all of matched XML nodes. 162`Find` panics if provided with an invalid XPath query, while `QueryAll` returns 163an error. 164 165#### Can I save my query expression object for the next query? 166 167Yes, you can. We provide `QuerySelector` and `QuerySelectorAll` methods; they 168accept your query expression object. 169 170Caching a query expression object avoids recompiling the XPath query 171expression, improving query performance. 172 173#### Create XML document. 174 175```go 176doc := &xmlquery.Node{ 177 Type: xmlquery.DeclarationNode, 178 Data: "xml", 179 Attr: []xml.Attr{ 180 xml.Attr{Name: xml.Name{Local: "version"}, Value: "1.0"}, 181 }, 182} 183root := &xmlquery.Node{ 184 Data: "rss", 185 Type: xmlquery.ElementNode, 186} 187doc.FirstChild = root 188channel := &xmlquery.Node{ 189 Data: "channel", 190 Type: xmlquery.ElementNode, 191} 192root.FirstChild = channel 193title := &xmlquery.Node{ 194 Data: "title", 195 Type: xmlquery.ElementNode, 196} 197title_text := &xmlquery.Node{ 198 Data: "W3Schools Home Page", 199 Type: xmlquery.TextNode, 200} 201title.FirstChild = title_text 202channel.FirstChild = title 203fmt.Println(doc.OutputXML(true)) 204// <?xml version="1.0"?><rss><channel><title>W3Schools Home Page</title></channel></rss> 205``` 206 207Quick Tutorial 208=== 209 210```go 211import ( 212 "github.com/antchfx/xmlquery" 213) 214 215func main(){ 216 s := `<?xml version="1.0" encoding="UTF-8" ?> 217<rss version="2.0"> 218<channel> 219 <title>W3Schools Home Page</title> 220 <link>https://www.w3schools.com</link> 221 <description>Free web building tutorials</description> 222 <item> 223 <title>RSS Tutorial</title> 224 <link>https://www.w3schools.com/xml/xml_rss.asp</link> 225 <description>New RSS tutorial on W3Schools</description> 226 </item> 227 <item> 228 <title>XML Tutorial</title> 229 <link>https://www.w3schools.com/xml</link> 230 <description>New XML tutorial on W3Schools</description> 231 </item> 232</channel> 233</rss>` 234 235 doc, err := xmlquery.Parse(strings.NewReader(s)) 236 if err != nil { 237 panic(err) 238 } 239 channel := xmlquery.FindOne(doc, "//channel") 240 if n := channel.SelectElement("title"); n != nil { 241 fmt.Printf("title: %s\n", n.InnerText()) 242 } 243 if n := channel.SelectElement("link"); n != nil { 244 fmt.Printf("link: %s\n", n.InnerText()) 245 } 246 for i, n := range xmlquery.Find(doc, "//item/title") { 247 fmt.Printf("#%d %s\n", i, n.InnerText()) 248 } 249} 250``` 251 252List of supported XPath query packages 253=== 254| Name | Description | 255| ------------------------------------------------- | ----------------------------------------- | 256| [htmlquery](https://github.com/antchfx/htmlquery) | XPath query package for HTML documents | 257| [xmlquery](https://github.com/antchfx/xmlquery) | XPath query package for XML documents | 258| [jsonquery](https://github.com/antchfx/jsonquery) | XPath query package for JSON documents | 259 260 Questions 261=== 262Please let me know if you have any questions 263