获取原始元素表示,包括开始和结束标签

我知道 golang xml,innerxml标签,它允许将元素内部内容作为原始 xml 获取。但我需要的是获取整个元素(开放标签、内部内容、关闭标签)作为原始数据。


这是一个我想以这种方式解析的示例。我想获得整体<Useful>及其所有可能的属性元素,并避免获得无用的元素。


package main


import (

    "encoding/xml"

    "fmt"

)


const data = `<Document>

    <Useless1>

        blah-blah

    </Useless1>

    <Useless2>

        blah-blah

    </Useless2>

    <Useful someAttr="someVal">

        <InnerField1>Inner field 1 value</InnerField1>

        <InnerField2>Inner field 2 value</InnerField2>

        <InnerField3>Inner field 3 value</InnerField3>

    </Useful>

    <Useless3>

        blah-blah

    </Useless3>

</Document>

`


func main() {

    doc := Document{}

    err := xml.Unmarshal([]byte(data), &doc)

    if err != nil {

        panic(err)

    }


    fmt.Println(doc.Useful.Data)

}


type Document struct {

    XMLName xml.Name `xml:"Document"`

    Useful  struct {

        Data string `xml:",innerxml"`

    } `xml:"Useful"`

}

游乐场中代码的链接位于: https: //goplay.space/#0KDXiRKDwlY

这就是我得到的:

    <InnerField1>Inner field 1 value</InnerField1>
    <InnerField2>Inner field 2 value</InnerField2>
    <InnerField3>Inner field 3 value</InnerField3>

这就是我想要得到的:

<Useful someAttr="someVal">
    <InnerField1>Inner field 1 value</InnerField1>
    <InnerField2>Inner field 2 value</InnerField2>
    <InnerField3>Inner field 3 value</InnerField3></Useful>

请注意,我正在使用的实际结构要复杂得多。我不想将整个<Document>内部内容作为原始 xml 获取,然后对其进行解析,尝试手动删除无用的元素。该<Useful>部分各不相同,因此我无法对例如属性进行硬编码,因为它们可能因一个文档而异。


至尊宝的传说
浏览 82回答 1
1回答

料青山看我应如是

也捕获属性您可以在结构中使用附加字段Useful来捕获(类型切片的xml.Attr)所有属性,如下所示:Useful  struct {    Attrs []xml.Attr `xml:",any,attr"`    Data  string     `xml:",innerxml"`} `xml:"Useful"`添加另一个属性时<Useful>:<Useful someAttr="someVal" someAttr2="someVal2">    ...<Useful>并使用 输出结果fmt.Printf("%+v", doc.Useful),输出将是(在Go Playground上尝试一下):{Attrs:[{Name:{Space: Local:someAttr} Value:someVal} {Name:{Space: Local:someAttr2} Value:someVal2}] Data:         <InnerField1>Inner field 1 value</InnerField1>         <InnerField2>Inner field 2 value</InnerField2>         <InnerField3>Inner field 3 value</InnerField3>     }真正获得完整的原始 XML另一种更复杂的方法是使用xml.Decoder标记读取输入,并标记 的开始和结束位置<Useful>。然后你就可以获得完整的原始XML <Useful>。它可能是这样的:dec := xml.NewDecoder(strings.NewReader(data))var start, end int64foundStart := falsefor {    if !foundStart {        start = dec.InputOffset()    }    t, err := dec.Token()    if err != nil {        if err != io.EOF {            fmt.Println(err)        }        break    }    if se, ok := t.(xml.StartElement); ok {        if se.Name.Local == "Useful" {            foundStart = true        }    }    if se, ok := t.(xml.EndElement); ok {        if se.Name.Local == "Useful" {            end = dec.InputOffset()            // We may break here, we got what we wanted            break        }    }}fmt.Println(data[start:end])它输出(在Go Playground上尝试):<Useful someAttr="someVal" someAttr2="someVal2">        <InnerField1>Inner field 1 value</InnerField1>        <InnerField2>Inner field 2 value</InnerField2>        <InnerField3>Inner field 3 value</InnerField3>    </Useful>由于我们不处理 的内容,因此我们可以通过如下<Useful>使用来加快速度:Decoder.Skip()dec := xml.NewDecoder(strings.NewReader(data))var start, end int64for {    start = dec.InputOffset()    t, err := dec.Token()    if err != nil {        if err != io.EOF {            fmt.Println(err)        }        break    }    if se, ok := t.(xml.StartElement); ok {        if se.Name.Local != "Useful" {            continue        }        if err := dec.Skip(); err != nil {            fmt.Println(err)            break        }        end = dec.InputOffset()        break    }}fmt.Println(data[start:end])输出是一样的。在Go Playground上试试这个。
打开App,查看更多内容
随时随地看视频慕课网APP