etree

repository·main·Indexed 23 days ago

https://github.com/beevik/etree

A lightweight, pure Go package that represents XML as an element tree, inspired by Python's ElementTree. It provides tools for easy traversal, modification, and creation of XML documents, including support for XPath-like queries, CDATA, processing instructions, and customizable read/write settings.

Tokens
4.3K
Snippets
4
Records
21
Agent score
81%

What's inside etree

  1. Perform path queries with XPath-like syntax

    main

    etree supports lightweight XPath-like queries to find elements within a document.

    Query Types

    • Recursive Search: Use the // prefix to search for elements at any level of the hierarchy (e.g., //book[@category='WEB']/title).
    • Direct Path: Use ./ or absolute paths to navigate specific hierarchies (e.g., ./bookstore/book[1]/*).
    • Predicates: Use square brackets [] for filtering, such as attribute matching [@attr='val'] or index selection [1].

    Methods

    • FindElementsSeq(path): Executes a path query and returns a sequence of matching elements.
    • FindElementsPathSeq(compiledPath): Executes a query using a pre-compiled path object. Use this for performance if you plan to run the same query multiple times.
    • MustCompilePath(path): Compiles a path string into a path object. It panics if the path is invalid.
    // Recursive search
    for _, t := range doc.FindElementsSeq("//book[@category='WEB']/title") {
        fmt.Println("Title:", t.Text())
    }
    
    // Direct path with index and wildcard
    for _, e := range doc.FindElementsSeq("./bookstore/book[1]/*") {
        fmt.Printf("%s: %s\n", e.Tag, e.Text())
    }
    
    // Using pre-compiled paths for performance
    path := etree.MustCompilePath("./bookstore/book[p:price='49.99']/title")
    for _, e := doc.FindElementsPathSeq(path) {
        fmt.Println(e.Text())
    }
  2. Create an XML document from scratch

    main

    You can build an XML document programmatically using etree.NewDocument(). This allows you to create processing instructions, elements, comments, and attributes. Use Indent(n) to format the output with a specific number of spaces/tabs and WriteTo(io.Writer) to serialize the document.

    Key methods:

    • NewDocument(): Initializes a new document.
    • CreateProcInst(name, value): Creates a processing instruction.
    • CreateElement(tag): Creates a new child element.
    • CreateComment(text): Adds a comment to an element.
    • CreateAttr(key, value): Adds an attribute to an element.
    • Indent(n): Sets indentation level.
    • WriteTo(w): Writes the document to an io.Writer.
    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)
  3. Read XML from files, strings, or readers

    main

    The etree.Document type provides several ways to load XML data:

    • From a file: Use ReadFromFile(filename string).
    • From other sources: You can also read XML from a string, a byte slice, or an io.Reader (though specific methods for these are referenced in the documentation rather than explicitly shown in this snippet).

    Note that ReadFromFile returns an error that should be handled.

    doc := etree.NewDocument()
    if err := doc.ReadFromFile("bookstore.xml"); err != nil {
        panic(err)
    }
  4. Process XML elements and attributes

    main

    Once a document is loaded, you can traverse and inspect it using selection methods.

    Common patterns:

    • SelectElement(tag): Finds the first child element with the given tag.
    • SelectElementsSeq(tag): Returns a sequence of all child elements matching the tag.
    • SelectAttrValue(key, defaultValue): Retrieves the value of an attribute, returning a default if not found.
    • Text(): Returns the text content of an element.
    • Attr: A slice of attributes available on an element for direct iteration.
    • Tag: The name of the element.
    root := doc.SelectElement("bookstore")
    fmt.Println("ROOT element:", root.Tag)
    
    for _, book := range root.SelectElementsSeq("book") {
        fmt.Println("CHILD element:", book.Tag)
        if title := book.SelectElement("title"); title != nil {
            lang := title.SelectAttrValue("lang", "unknown")
            fmt.Printf("  TITLE: %s (%s)\n", title.Text(), lang)
        }
        for _, attr := range book.Attr {
            fmt.Printf("  ATTR: %s=%s\n", attr.Key, attr.Value)
        }
    }
  5. How etree paths work: Selectors and Filters

    main

    An etree Path is a sequence of segments separated by slashes (/). Each segment consists of a selector and zero or more filters.

    1. Selectors determine which elements are considered for the next step in the path (e.g., * for all children, // for all descendants, or a specific tag name).
    2. Filters (enclosed in []) then refine that list of candidates based on attributes, child elements, text content, or namespace information.

    Path Examples

    • Select root child: /bookstore
    • Select descendants with attribute: //book[@category='WEB']/title
    • Select first descendant matching text: .//book[title='Great Expectations'][1]
    • Select children with specific attribute value: ./book/*[@language='english']
    • Select descendants by namespace: .//book[namespace-uri()='http://www.w3.org/TR/html4/']
  6. Configure XML writing and indentation with WriteSettings and IndentSettings

    main

    Control how the XML document is serialized using WriteSettings and IndentSettings.

    WriteSettings:

    • CanonicalEndTags: Forces production of end tags for empty elements.
    • CanonicalText: Forces character references for &, <, and >.
    • CanonicalAttrVal: Forces character references for attribute values.
    • AttrSingleQuote: Uses single quotes for attributes instead of double quotes.

    IndentSettings:

    • Spaces: Number of spaces per level. Use etree.NoIndent (-1) to remove all indentation.
    • UseTabs: Uses tabs instead of spaces.
    • UseCRLF: Uses \r\n for newlines instead of \n.
    • PreserveLeafWhitespace: Preserves whitespace in elements containing only non-CDATA data.
    • SuppressTrailingWhitespace: Removes trailing whitespace at the end of the document.
  7. Configure XML reading behavior with ReadSettings

    main

    Use ReadSettings to control how XML is parsed into a Document. Key options include:

    • CharsetReader: A function to convert non-UTF-8 charsets to UTF-8.
    • Permissive: If true, allows common XML mistakes like missing tags or attribute values.
    • PreserveCData: If true, preserves CDATA blocks as distinct tokens instead of converting them to normal text.
    • PreserveDuplicateAttrs: If true, preserves multiple attributes with the same name.
    • ValidateInput: If true, performs a full well-formedness check before parsing (incurs a performance penalty).
    • AutoClose: A list of tags to consider closed immediately after opening (e.g., xml.HTMLAutoClose).
    • MaxDepth: Limits the tree depth to prevent stack overflow. Defaults to 1024 if set to 0 or less.
  8. Compile XPath-like paths with CompilePath and MustCompilePath

    main

    To search an XML tree, you must first compile an XPath-like string into a Path object.

    • Use CompilePath(path string) (Path, error) for dynamic paths where you need to handle potential syntax errors.
    • Use MustCompilePath(path string) Path for hard-coded paths. This function will panic if the path is invalid.

    Compiled Path objects are optimized and can be used with an Element's Find* methods to locate desired elements.

  9. Create and manage an XML Document

    main

    A Document is a container for a complete XML tree. It holds a single embedded element (the root) and manages read/write settings.

    • NewDocument(): Creates an empty document without a root.
    • NewDocumentWithRoot(e *Element): Creates a document and sets the provided element as the root.
    • doc.SetRoot(e): Replaces the current root with element e. If e was part of another document, it is unbound first.
    • doc.Root(): Returns the root element or nil.
    • doc.Copy(): Returns a deep, recursive copy of the document.

    Reading/Writing:

    • doc.ReadFrom(r io.Reader): Reads XML from a reader.
    • doc.ReadFromFile(path string): Reads XML from a file.
    • doc.WriteTo(w io.Writer): Serializes the document to a writer.
    • doc.WriteToFile(path string): Serializes the document to a file.
  10. Create and manage text and CDATA nodes

    main

    You can create character data (text or CDATA) either as standalone tokens or as children of an element.

    Standalone Creation

    • NewText(text string) *CharData: Creates an unparented text node.
    • NewCData(data string) *CharData: Creates an unparented CDATA section.

    Adding to an Element

    • e.CreateText(text string) *CharData: Adds a text node to the end of the element's children.
    • e.CreateCData(data string) *CharData: Adds a CDATA section to the end of the element's children.

    Modifying CharData

    • c.SetData(text string): Modifies the content of a *CharData node. If the new text is whitespace, it is flagged as such.
  11. Indent an XML element with settings

    main

    The IndentWithSettings(s *IndentSettings) method modifies an *Element and its entire child tree by inserting character data tokens containing newlines and indentation.

    This function treats the element as if it were at the root of a document, making it most useful when called immediately before writing an element as an XML fragment using WriteTo.

  12. Create and manipulate XML Elements

    main

    An Element represents an XML tag, its attributes, and its children (elements, text, comments, etc.).

    Creation:

    • NewElement(tag string): Creates an unparented element. The tag can include a namespace prefix (e.g., "prefix:tag").
    • e.CreateElement(tag string): Creates a new element and adds it as the last child of e.
    • e.CreateChild(tag string, cont func(e *Element)): Creates a child and immediately executes a callback function on it. This is ideal for building nested structures.

    Attributes:

    • e.SelectAttr(key string): Returns a pointer to the Attr if found, otherwise nil.
    • e.SelectAttrValue(key, dflt string): Returns the attribute value or the provided default.

    Text and CDATA:

    • e.Text(): Returns all character data immediately following the opening tag.
    • e.SetText(text string): Replaces the element's immediate text content.
    • e.SetCData(text string): Replaces the element's immediate text content with a CDATA section.