草庐IT

xml - 将子元素的属性直接解析为 Go struct

coder 2023-07-03 原文

在使用 Go 解析 XML 时,如何将嵌套元素的属性直接读取到我的结构中?

我的 XML 如下所示。它是 OpenStreetMap 格式的一部分:

<way id="123" >
        <nd ref="101"/>
        <!-- Lots of nd elements repeated -->
        <nd ref="109"/>
</way>

我有

type Way struct {
    Nodes []NodeRef `xml:"nd"`
}

type NodeRef struct {
    Ref int `xml:"ref,attr"`
}

但我希望能够做到

type Way struct {
    Nodes []int `???`
}

直接。

关于 Unmarshalling 的文档没有帮助我。我试过使用 xml:"nd>ref,attr" 但失败并显示“chain not valid with attr flag”。

请看下面的示例代码。 Run the code in Go Playground

package main

import (
    "encoding/xml"
    "fmt"
    "io"
    "os"
    "strings"
)

func main() {
    data := `
        <way id="5090250" >
        <nd ref="822403"/>
        <nd ref="21533912"/>
        <nd ref="821601"/>
        <nd ref="21533910"/>
        <nd ref="135791608"/>
        <nd ref="333725784"/>
        <nd ref="333725781"/>
        <nd ref="333725774"/>
        <nd ref="333725776"/>
        <nd ref="823771"/>
      </way>
    `

    r := strings.NewReader(data)
    way, err := ReadWay(r)
    if err != nil {
        fmt.Println("Could not read", err)
        os.Exit(1)
    }

    fmt.Println(way)
}

// I'd like to get rid of this nested struct.
type NodeRef struct {
    Ref int `xml:"ref,attr"`
}

type Way struct {
    ID int `xml:"id,attr"`
    // How can I write all <nd ref="123"/> directly into Nodes []int?
    Nodes []NodeRef `xml:"nd"`
}

func ReadWay(reader io.Reader) (Way, error) {
    var way Way
    if err := xml.NewDecoder(reader).Decode(&way); err != nil {
        return way, err // Why can't I return nil, err?
    }
    return way, nil
}

最佳答案

简而言之,您不能直接这样做。绕过 XML 结构的常见模式是实现 xml.Unmarshaler 接口(interface)。这是一个例子:

type Way struct {
    ID    int 
    Nodes []int
}

func (w *Way) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    var payload struct {
        ID    int `xml:"id,attr"`
        Nodes []struct {
            Ref int `xml:"ref,attr"`
        } `xml:"nd"`
    }   

    err := d.DecodeElement(&payload, &start)
    if err != nil {
        return err 
    }   

    w.ID = payload.ID
    w.Nodes = make([]int, 0, len(payload.Nodes))

    for _, node := range payload.Nodes {
        w.Nodes = append(w.Nodes, node.Ref)
    }   

    return nil 
}

在这里,payload 变量是根据您的 XML 数据建模的,而 Way 结构是按照您希望的方式建模的。解码有效负载后,您可以根据需要使用它来初始化 Way 变量……

旁注: //为什么我不能返回 nil,呃?

您不能返回 nil 因为 Way 既不是指针也不是接口(interface),因此 nil 不是有效值

关于xml - 将子元素的属性直接解析为 Go struct,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36279414/

有关xml - 将子元素的属性直接解析为 Go struct的更多相关文章

  1. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 用逗号、双引号和编码解析 csv - 2

    我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

  4. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  5. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  6. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  7. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  8. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  9. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  10. ruby-on-rails - 我更新了 ruby​​ gems,现在到处都收到解析树错误和弃用警告! - 2

    简而言之错误:NOTE:Gem::SourceIndex#add_specisdeprecated,useSpecification.add_spec.Itwillberemovedonorafter2011-11-01.Gem::SourceIndex#add_speccalledfrom/opt/local/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:91./opt/local/lib/ruby/gems/1.8/gems/rails-2.3.8/lib/rails/gem_dependency.rb:275:in`==':und

随机推荐