Go XML解析:将缺失的属性设置为”true”。

huangapple go评论67阅读模式
英文:

Go XML parsing: set missing attributes to "true"

问题

以下是翻译好的内容:

下面的代码片段:

package main
import (
	"encoding/xml"
	"fmt"
)

func main() {
	var r struct {
		Item []struct {
			Value string `xml:"value,attr"`
			Flag bool `xml:"flag,attr"`
		} `xml:"item"`
	}
	xml.Unmarshal([]byte(`
		<result>
			<item value="1" flag="false" />
			<item value="2" flag="true" />
			<item value="3" />
		</result>`,
	), &r)
	fmt.Printf("%+v\n", r)
}

将打印以下结果:

{Item:[{Value:1 Flag:false} {Value:2 Flag:true} {Value:3 Flag:false}]}

在某些元素中,flag 属性可能会缺失(例如上面的 item 3),但我希望它的默认值为 true,而不是 false

  1. 我不能在构造函数中赋值,因为我不知道数组中元素的数量。
  2. 我不能使用实现了 UnmarshalerAttr 接口的自定义类型,并在解组过程中进行赋值,因为如果属性缺失,UnmarshalXMLAttr 方法不会被调用。
  3. 我可以将其定义为指针,然后检查是否为 nil,然后设置为 true,但这样做很繁琐且容易出错。

我该如何解决这个问题?

英文:

The snippet below,

package main
import (
	&quot;encoding/xml&quot;
	&quot;fmt&quot;
)

func main() {
	var r struct {
		Item []struct {
			Value string `xml:&quot;value,attr&quot;`
			Flag bool `xml:&quot;flag,attr&quot;`
		} `xml:&quot;item&quot;`
	}
	xml.Unmarshal([]byte(`
		&lt;result&gt;
			&lt;item value=&quot;1&quot; flag=&quot;false&quot; /&gt;
			&lt;item value=&quot;2&quot; flag=&quot;true&quot; /&gt;
			&lt;item value=&quot;3&quot; /&gt;
		&lt;/result&gt;`,
	), &amp;r)
	fmt.Printf(&quot;%+v\n&quot;, r)
}

Will print the following result:

{Item:[{Value:1 Flag:false} {Value:2 Flag:true} {Value:3 Flag:false}]}

In some elements, flag attribute will be missing (e.g. item 3 above), but I want it to take the default value of true, instead than false.

  1. I cannot assign it in the constructor, because I don't know the number of elements in the array upfront.
  2. I cannot use a custom type that implements UnmarshalerAttr and assign during unmarshaling because if the attribute is missing, UnmarshalXMLAttr is not run.
  3. I could make it a pointer, and then check if nil, then true, but that's just gross and error-prone.

How would I go about doing this?

答案1

得分: 5

你是正确的,你不能使用UnmarshalerAttr来实现这个功能。相反,ResultItem可以实现Unmarshaler,这将允许你设置默认的属性值:

package main
import (
    "encoding/xml"
    "fmt"
)

type ResultItem struct {
  Value string `xml:"value,attr"`
  Flag bool `xml:"flag,attr"`
}

func (ri *ResultItem) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
  type resultItem ResultItem // new type to prevent recursion
  item := resultItem{
    Flag: true,
  }
  if err := d.DecodeElement(&item, &start); err != nil {
    return err
  }
  *ri = (ResultItem)(item)
  return nil
}

func main() {
    var r struct {
      Item[] ResultItem `xml:"item"`
    }
    xml.Unmarshal([]byte(`
        <result x="ASDASD">
            <item value="1" flag="false" />
            <item value="2" flag="true" />
            <item value="3" />
        </result>`,
    ), &r)
    fmt.Printf("%+v\n", r)
}

希望对你有帮助!

英文:

You're correct in that you cannot use UnmarshalerAttr for this. Instead, ResultItem can implement Unmarshaler which will allow you to set default attribute values:

package main
import (
    &quot;encoding/xml&quot;
    &quot;fmt&quot;
)

type ResultItem struct {
  Value string `xml:&quot;value,attr&quot;`
  Flag bool `xml:&quot;flag,attr&quot;`
}

func (ri *ResultItem) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
  type resultItem ResultItem // new type to prevent recursion
  item := resultItem{
    Flag: true,
  }
  if err := d.DecodeElement(&amp;item, &amp;start); err != nil {
    return err
  }
  *ri = (ResultItem)(item)
  return nil
}

func main() {
    var r struct {
      Item[] ResultItem `xml:&quot;item&quot;`
    }
    xml.Unmarshal([]byte(`
        &lt;result x=&quot;ASDASD&quot;&gt;
            &lt;item value=&quot;1&quot; flag=&quot;false&quot; /&gt;
            &lt;item value=&quot;2&quot; flag=&quot;true&quot; /&gt;
            &lt;item value=&quot;3&quot; /&gt;
        &lt;/result&gt;`,
    ), &amp;r)
    fmt.Printf(&quot;%+v\n&quot;, r)
}

huangapple
  • 本文由 发表于 2014年11月16日 20:21:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/26956845.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定