【问题标题】:mixed XML decoding in golang preserving ordergolang保留顺序中的混合XML解码
【发布时间】:2015-11-18 03:47:30
【问题描述】:

我需要从 XML 中提取报价,但要考虑节点顺序:

产品> 项目>

以下结构会将值解码,但会分成两个不同的切片,这将导致原始顺序丢失:

类型提供结构{ 提供[]offer`xml:“items>offer”` 产品 []offer `xml:"items>product>offer"` }

有什么想法吗?

【问题讨论】:

  • 不要解组 XML:通过调用 Token 方法使用 xml.Decoder 对元素进行解码。 (抱歉,我手头没有示例。)
  • ...或使用XPath 在文档中查询位于元素“items”下的所有名为“offer”的节点。 XPath 在中小型文档上工作得相当好,否则我会接受@Volker 的建议。

标签: xml go slice xml-deserialization


【解决方案1】:

一种方法是覆盖UnmarshalXML 方法。假设我们的输入如下所示:

<doc>
    <head>My Title</head>
    <p>A first paragraph.</p>
    <p>A second one.</p>
</doc>

我们想要反序列化文档并保留标题和段落的顺序。为了订购,我们需要一片。为了同时容纳headp,我们需要一个接口。我们可以这样定义我们的文档:

type Document struct {
    XMLName  xml.Name `xml:"doc"`
    Contents []Mixed  `xml:",any"`
}

,any 注释会将 any 元素收集到Contents 中。它是一个Mixed 类型,我们需要将其定义为一个类型:

type Mixed struct {
    Type  string      // just keep "head" or "p" in here
    Value interface{} // keep the value, we could use string here, too
}

我们需要对反序列化过程进行更多控制,因此我们通过实现UnmarshalXMLMixed 变为xml.Unmashaler。我们根据起始元素的名称来决定代码路径,例如headp。在这里,我们只使用一些值填充我们的 Mixed 结构,但您基本上可以在这里做任何事情:

func (m *Mixed) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    switch start.Name.Local {
    case "head", "p":
        var e string
        if err := d.DecodeElement(&e, &start); err != nil {
            return err
        }
        m.Value = e
        m.Type = start.Name.Local
    default:
        return fmt.Errorf("unknown element: %s", start)
    }
    return nil
}

综上所述,上述结构的用法如下所示:

func main() {
    s := `
    <doc>
        <head>My Title</head>
        <p>A first paragraph.</p>
        <p>A second one.</p>
    </doc>
    `

    var doc Document
    if err := xml.Unmarshal([]byte(s), &doc); err != nil {
        log.Fatal(err)
    }
    fmt.Printf("#%v", doc)
}   

哪个会打印出来。

#{{ doc} [{head My Title} {p A first paragraph.} {p A second one.}]}

我们保留了顺序并保留了一些类型信息。您可以使用许多不同的类型来进行反序列化,而不是像 Mixed 这样的单一类型。这种方法的代价是你的容器——这里是文档的Contents 字段——是一个接口。要执行任何特定于元素的操作,您需要一个类型断言或一些辅助方法。

播放完整代码:https://play.golang.org/p/fzsUPPS7py

【讨论】:

    猜你喜欢
    • 2018-12-24
    • 2022-07-03
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 1970-01-01
    相关资源
    最近更新 更多