zoukankan      html  css  js  c++  java
  • golang学习笔记 ---etree包

    关于Etree XML官方文档

    etree
    The etree package is a lightweight, pure go package that expresses XML in the form of an element tree. Its design was inspired by the Python ElementTree module.

    Some of the package's capabilities and features:

    Represents XML documents as trees of elements for easy traversal.
    Imports, serializes, modifies or creates XML documents from scratch.
    Writes and reads XML to/from files, byte slices, strings and io interfaces.
    Performs simple or complex searches with lightweight XPath-like query APIs.
    Auto-indents XML using spaces or tabs for better readability.
    Implemented in pure go; depends only on standard go libraries.
    Built on top of the go encoding/xml package.

    范例1:创建一个XML文档

    package main
    
    import (
    	"os"
    	etree "github.com/beevik/etree"
    )
    
    func main() {
    
    	doc := etree.NewDocument()
    	doc.CreateProcInst("xml", `version="1.0" encoding="UTF-8"`)
    	doc.CreateProcInst("xml-stylesheet", `type="text/xsl" href="style.xsl"`)
    
    	people := doc.CreateElement("People")
    	people.CreateComment("These are all known people")
    
    	jon := people.CreateElement("Person")
    	jon.CreateAttr("name", "Jon")
    
    	sally := people.CreateElement("Person")
    	sally.CreateAttr("name", "Sally")
    
    	doc.Indent(2)
    	doc.WriteTo(os.Stdout)
    }
    

      

    输出:

    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-stylesheet type="text/xsl" href="style.xsl"?>
    <People>
      <!--These are all known people-->
      <Person name="Jon"/>
      <Person name="Sally"/>
    </People>
    

      

    eading an XML file

    Suppose you have a file on disk called bookstore.xml containing the following data:

    <bookstore xmlns:p="urn:schemas-books-com:prices">
     
      <book category="COOKING">
        <title lang="en">Everyday Italian</title>
        <author>Giada De Laurentiis</author>
        <year>2005</year>
        <p:price>30.00</p:price>
      </book>
     
      <book category="CHILDREN">
        <title lang="en">Harry Potter</title>
        <author>J K. Rowling</author>
        <year>2005</year>
        <p:price>29.99</p:price>
      </book>
     
      <book category="WEB">
        <title lang="en">XQuery Kick Start</title>
        <author>James McGovern</author>
        <author>Per Bothner</author>
        <author>Kurt Cagle</author>
        <author>James Linn</author>
        <author>Vaidyanathan Nagarajan</author>
        <year>2003</year>
        <p:price>49.99</p:price>
      </book>
     
      <book category="WEB">
        <title lang="en">Learning XML</title>
        <author>Erik T. Ray</author>
        <year>2003</year>
        <p:price>39.95</p:price>
      </book>
     
    </bookstore>
    

      

    This code reads the file's contents into an etree document.

    doc := etree.NewDocument()
    if err := doc.ReadFromFile("bookstore.xml"); err != nil {
    panic(err)
    }
    

      


    You can also read XML from a string, a byte slice, or an io.Reader.

    Processing elements and attributes

    This example illustrates several ways to access elements and attributes using etree selection queries.

    root := doc.SelectElement("bookstore")
    fmt.Println("ROOT element:", root.Tag)
     
    for _, book := range root.SelectElements("book") {
        fmt.Println("CHILD element:", book.Tag)
        if title := book.SelectElement("title"); title != nil {
            lang := title.SelectAttrValue("lang", "unknown")
            fmt.Printf("  TITLE: %s (%s)
    ", title.Text(), lang)
        }
        for _, attr := range book.Attr {
            fmt.Printf("  ATTR: %s=%s
    ", attr.Key, attr.Value)
        }
    }
    

      

    完整实例:

    package main
    
    import (
    	"fmt"
    
    	etree "github.com/beevik/etree"
    )
    
    func main() {
    
    	doc := etree.NewDocument()
    	if err := doc.ReadFromFile("bookstore.xml"); err != nil {
    		panic(err)
    	}
    
    	root := doc.SelectElement("bookstore")
    	fmt.Println("ROOT element:", root.Tag)
    
    	for _, book := range root.SelectElements("book") {
    		fmt.Println("CHILD element:", book.Tag)
    		if title := book.SelectElement("title"); title != nil {
    			lang := title.SelectAttrValue("lang", "unknown")
    			fmt.Printf("  TITLE: %s (%s)
    ", title.Text(), lang)
    		}
    		for _, attr := range book.Attr {
    			fmt.Printf("  ATTR: %s=%s
    ", attr.Key, attr.Value)
    		}
    	}
    }
    

      输出:

    ROOT element: bookstore

    CHILD element: book

    TITLE: Everyday Italian (en)

    ATTR: category=COOKING

    CHILD element: book

    TITLE: Harry Potter (en)

    ATTR: category=CHILDREN

    CHILD element: book

    TITLE: XQuery Kick Start (en)

    ATTR: category=WEB

    CHILD element: book

    TITLE: Learning XML (en)

    ATTR: category=WEB

    
    

    Path queries
    This example uses etree's path functions to select all book titles that fall into the category of 'WEB'. The double-slash prefix in the path causes the search for book elements to occur recursively; book elements may appear at any level of the XML hierarchy.

    for _, t := range doc.FindElements("//book[@category='WEB']/title") {
        fmt.Println("Title:", t.Text())
    }
    

     

    Output:

    Title: XQuery Kick Start
    Title: Learning XML
    

      

     

    This example finds the first book element under the root bookstore element and outputs the tag and text of each of its child elements.

    for _, e := range doc.FindElements("./bookstore/book[1]/*") {
        fmt.Printf("%s: %s
    ", e.Tag, e.Text())
    }
    

     Output:

    title: Everyday Italian
    author: Giada De Laurentiis
    year: 2005
    price: 30.00
    

      

    This example finds all books with a price of 49.99 and outputs their titles.

    path := etree.MustCompilePath("./bookstore/book[p:price='49.99']/title")
    for _, e := range doc.FindElementsPath(path) {
        fmt.Println(e.Text())
    }
    

      

    Output:

    XQuery Kick Start
    

      

    Note that this example uses the FindElementsPath function, which takes as an argument a pre-compiled path object. Use precompiled paths when you plan to search with the same path more than once.

    Other features
    These are just a few examples of the things the etree package can do. See the documentation for a complete description of its capabilities.

    Contributing
    This project accepts contributions. Just fork the repo and submit a pull request!

    
    

    etree作为一个轮子在解析XML文件的工具中占据着很重要的地位,它可以查找节点,轮询、生成XML文件。

    一、XML的引入写法
    在工程中引入XML的方法,建议用第一种

    //方法一

    xml := `
    <bookstore>
    	<book>
    		<title>Great Expectations</title>
    		<author>Charles Dickens</author>
    	</book>
    	<book>
    		<title>Ulysses</title>
    		<author>James Joyce</author>
    	</book>
    </bookstore>`


    //方法二

    LoginPut= "<?xml version="1.0" encoding="UTF-8" standalone="yes"?>" +
    		" <LogonRequest xmlns="http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/"" +
    		" schemaVersion="V1_1_0">" +
    		" <Metadata>" +
    		" <Atom/>" +
    		" </Metadata>" +
    		" <UserID >%s</UserID>" +
    		" <Password >%s</Password>" +
    		" </LogonRequest>"
    

      

    二、XML的解析

    1. 判断所需节点是否存在的方法

    方法1:在某个节点范围下查找指定节点是否存在

    //whetherExistNode  判断节点是否存在
    func whetherExistNode(doc etree.Element, nodeName string) (exist bool) {
    	path := etree.MustCompilePath(nodeName)
    	bb := doc.FindElementPath(path)
    	if bb != nil {
    		return true
    	} else {
    		return false
    	}
    	return exist
    }
    

      

    方法2:获取指定节点的值

    //getSpecifiedNodeVal 获取指定节点的值
    func getSpecifiedNodeVal(doc etree.Document, nodeName string) (dataSlice []string) {
    	path := etree.MustCompilePath(nodeName)
    	var val string
    	for _, t := range doc.FindElementsPath(path) {
    		val = t.Text()
    		if len(dataSlice) <= 0 {
    			dataSlice = append(dataSlice, val)
    		} else {
    			repeat := false
    			for i := 0; i < len(dataSlice); i++ {
    				if dataSlice[i] == val {
    					repeat = true
    				}
    			}
    			if !repeat {
    				dataSlice = append(dataSlice, val)
    			}
    		}
    	}
    	return dataSlice
    }
    

      

    方法3:在用SelectElement获取节点值的时候 要判断改节点是否存在,如果不加判断,程序直接就会panic退出,后果会比较严重。

    	if tempNode.SelectElement("OperatingSystemVersion") != nil {
    		systemVersion = tempNode.SelectElement("OperatingSystemVersion").Text()
    		if systemVersion != "" {
    			systemType = util.GetOSType(systemVersion)
    		}
    	} else {
    		systemVersion = ""
    	}
    

      

    注意点:在用FindElementsPath或FindElements查找节点时建议用FindElementsPath,因为FindElements在查找不到节点时会panic报错,SelectElement和SelectElements,的用法,SelectElements获取到的结果为数组,SelectElement标识选中的单一的节点。

    	path := etree.MustCompilePath("//PartitionName")
    	doc.FindElementsPath(path)
    

      

    重点:1.在获取节点值的时候一定要判断节点是否为空

               2.添加//标识从头开始查找值

               3.doc.SelectElement必须选中开始的父节点,不能跨区域

        //FindElementPath  指定父节点查找指定的接点值:节点不存在不会报错
    	aa := doc.SelectElement("feed").SelectElement("entry")
    	path := etree.MustCompilePath("updatedd")
    	cc := aa.FindElementPath(path)
    	if cc != nil {
    		fmt.Println(cc.Text())
    	} else {
    		fmt.Println("cc == nil")
    	}
    

      

    2.etree支持接口返回内容和XML文件两种解析方式

    测试用的data.xml文件

    <feed xmlns="http://www.w3.org/2005/Atom" xmlns:ns2="http://a9.com/-/spec/opensearch/1.1/" xmlns:ns3="http://www.w3.org/1999/xhtml">
        <id>5134c4aa-8df4-3d41-aafc-927a7546f8b8</id>
        <updated>2019-09-25T03:03:29.615Z</updated>
        <link rel="SELF" href="https://192.168.10.51:12443/rest/api/uom/ManagedSystem/c13e47ce-5967-3845-a500-4b8947a9fb10/LogicalPartition"/>
        <link rel="MANAGEMENT_CONSOLE" href="https://192.168.10.51:12443/rest/api/uom/ManagementConsole/525cb072-1d11-3969-9245-053f0ac6f406"/>
        <generator>IBM Power Systems Management Console</generator>
        <entry>
            <id>323F5D6D-E501-4166-9522-B216B1565862</id>
            <title>LogicalPartition</title>
            <published>2019-09-25T03:03:29.914Z</published>
            <link rel="SELF" href="https://192.168.10.51:12443/rest/api/uom/ManagedSystem/c13e47ce-5967-3845-a500-4b8947a9fb10/LogicalPartition/323F5D6D-E501-4166-9522-B216B1565862"/>
            <author>
                <name>IBM Power Systems Management Console</name>
            </author>
            <etag:etag xmlns:etag="http://www.ibm.com/xmlns/systems/power/firmware/uom/mc/2012_10/" xmlns="http://www.ibm.com/xmlns/systems/power/firmware/uom/mc/2012_10/">-170243083</etag:etag>
     
        </entry>
        <entry>
            <id>21FE0160-FF83-4852-909B-B7D264E258C8</id>
            <title>LogicalPartition</title>
            <published>2019-09-25T03:03:29.916Z</published>
            <link rel="SELF" href="https://192.168.10.51:12443/rest/api/uom/ManagedSystem/c13e47ce-5967-3845-a500-4b8947a9fb10/LogicalPartition/21FE0160-FF83-4852-909B-B7D264E258C8"/>
            <author>
                <name>IBM Power Systems Management Console</name>
            </author>
            <etag:etag xmlns:etag="http://www.ibm.com/xmlns/systems/power/firmware/uom/mc/2012_10/" xmlns="http://www.ibm.com/xmlns/systems/power/firmware/uom/mc/2012_10/">-1052118977</etag:etag>
     
        </entry>
    </feed>
    

      

    var testData string = `<entry>
            <id>21FE0160-FF83-4852-909B-B7D264E258C8</id>
            <title>LogicalPartition</title>
            <published>2019-09-25T03:03:29.916Z</published>
            <link rel="SELF" href="https://192.168.10.51:12443/rest/api/uom/ManagedSystem/c13e47ce-5967-3845-a500-4b8947a9fb10/LogicalPartition/21FE0160-FF83-4852-909B-B7D264E258C8"/>
            <author>
                <name>IBM Power Systems Management Console</name>
            </author>
            <etag:etag xmlns:etag="http://www.ibm.com/xmlns/systems/power/firmware/uom/mc/2012_10/" xmlns="http://www.ibm.com/xmlns/systems/power/firmware/uom/mc/2012_10/">-1052118977</etag:etag>
        </entry>`
    
    package main
    
    import (
    	"fmt"
    
    	etree "github.com/beevik/etree"
    )
    
    var testData string = `<entry>
            <id>21FE0160-FF83-4852-909B-B7D264E258C8</id>
            <title>LogicalPartition</title>
            <published>2019-09-25T03:03:29.916Z</published>
            <link rel="SELF" href="https://192.168.10.51:12443/rest/api/uom/ManagedSystem/c13e47ce-5967-3845-a500-4b8947a9fb10/LogicalPartition/21FE0160-FF83-4852-909B-B7D264E258C8"/>
            <author>
                <name>IBM Power Systems Management Console</name>
            </author>
            <etag:etag xmlns:etag="http://www.ibm.com/xmlns/systems/power/firmware/uom/mc/2012_10/" xmlns="http://www.ibm.com/xmlns/systems/power/firmware/uom/mc/2012_10/">-1052118977</etag:etag>
        </entry>`
    
    func main() {
    
    	//读取字符串的方法-----------采用绝对路径的方法
    	doc := etree.NewDocument()
    	if err := doc.ReadFromString(testData); err != nil {
    		panic(err)
    	}
    	res := doc.FindElement("./entry[0]/id").Text()
    	fmt.Println(res)
    
    	// doc := etree.NewDocument()
    	// if err := doc.ReadFromFile("data.xml"); err != nil {
    	// 	panic(err)
    	// }
    	// servers := doc.SelectElement("feed")
    	// for _, server := range servers.SelectElements("entry") {
    
    	// 	if server.SelectElement("author").SelectElement("name") == nil {
    	// 		fmt.Println("测试节点不存在")
    	// 	} else {
    	// 		fmt.Println(server.SelectElement("author").SelectElement("name").Text())
    	// 	}
    	// }
    
    }
    

      输出:

    21FE0160-FF83-4852-909B-B7D264E258C8

    package main
    
    import (
    	"fmt"
    
    	etree "github.com/beevik/etree"
    )
    
    
    func main() {
    
    	doc := etree.NewDocument()
    	if err := doc.ReadFromFile("data.xml"); err != nil {
    		panic(err)
    	}
    	servers := doc.SelectElement("feed")
    	for _, server := range servers.SelectElements("entry") {
    
    		if server.SelectElement("author").SelectElement("name") == nil {
    			fmt.Println("测试节点不存在")
    		} else {
    			fmt.Println(server.SelectElement("author").SelectElement("name").Text())
    		}
    	}
    
    }
    

      输出:

    IBM Power Systems Management Console

    IBM Power Systems Management Console

  • 相关阅读:
    微信小程序左右滚动公告栏效果
    返回当前页面title、url等操作
    打开URL操作
    打开浏览器操作
    Java for selenium(webdriver) 环境搭建
    HTMLTestRunner 自动化测试报告
    Python特殊语法:filter、map、reduce、lambda [转]
    抽象类
    __str__
    WebTable 扩展
  • 原文地址:https://www.cnblogs.com/saryli/p/15384962.html
Copyright © 2011-2022 走看看