为了账号安全,请及时绑定邮箱和手机立即绑定

在两个命名空间中解组具有相同属性名称的 XML 属性

在两个命名空间中解组具有相同属性名称的 XML 属性

Go
富国沪深 2022-05-05 16:10:27
我有一个 XML 结构,其中有一个未命名空间的“类型”属性和一个命名空间属性。我无法让 GO 的解组器读取两个“类型”属性。XML 是:data := `<response xmlns="urn:debugger_protocol_v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><map name="bool" type="bool_T" xsi:type="xsd:boolean"></map><map name="int" type="int_T" xsi:type="xsd:decimal"></map></response>`我的 Go/XML 定义是:type Typemap struct {    XMLName xml.Name `xml:"map"`    Name    string   `xml:"name,attr"`    Type    string   `xml:"urn:debugger_protocol_v1 type,attr"`    XsiType string   `xml:"http://www.w3.org/2001/XMLSchema-instance type,attr"`}type Response struct {    XMLName xml.Name `xml:"response"`    Typemap []Typemap `xml:"map,omitempty"`}运行以下代码时:package mainimport (    "encoding/xml"    "fmt"    "strings")type Typemap struct {    XMLName xml.Name `xml:"map"`    Name    string   `xml:"name,attr"`    Type    string   `xml:"urn:debugger_protocol_v1 type,attr"`    XsiType string   `xml:"http://www.w3.org/2001/XMLSchema-instance type,attr"`}type Response struct {    XMLName xml.Name  `xml:"response"`    Typemap []Typemap `xml:"map,omitempty"`}func main() {    rq := new(Response)    data := `<response xmlns="urn:debugger_protocol_v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><map name="bool" type="bool_T" xsi:type="xsd:boolean"></map><map name="int" type="int_T" xsi:type="xsd:decimal"></map></response>`    reader := strings.NewReader(data)    decoder := xml.NewDecoder(reader)    err := decoder.Decode(&rq)    if err != nil {        fmt.Println(err)    }    fmt.Printf("Unmarshalled Content:\n%v", rq)}输出漏掉了bool_T,如下:&{{urn:debugger_protocol_v1 response} [    {{urn:debugger_protocol_v1 map} bool  xsd:boolean}    {{urn:debugger_protocol_v1 map} int  xsd:decimal}]}如果我urn:debugger_protocol_v1从定义中删除 ,我会收到以下错误:main.Typemap field "Type" with tag "type,attr" conflicts with field "XsiType" with tag "http://www.w3.org/2001/XMLSchema-instance type,attr"我无法更改原始 XML 数据格式。有没有办法解组这两个type属性?
查看完整描述

1 回答

?
米脂

TA贡献1836条经验 获得超3个赞

事实证明,目前没有办法在 Go 中原生地做到这一点。有一个与命名空间相关的问题列表,以及描述它的特定问题,但尚未解决。


但是,我也找到了一种解决方法。可以为属性和元素编写自己的解组代码。


对于属性,您可以实现以下内容:


type NonMarshalled string


func (s *NonMarshalled) UnmarshalXMLAttr(attr xml.Attr) error {

    fmt.Printf("Parsing attribute '%s', with value '%s'", attr.Name.Local, attr.Value)

    s.Title = strings.ToUpper(attr.Value)

    return nil

}


type Typemap struct {

    XMLName xml.Name `xml:"map"`

    Name    string   `xml:"name,attr"`

    Type    NonNamespaced `xml:"type,attr"`

    XsiType string   `xml:"http://www.w3.org/2001/XMLSchema-instance type,attr"`

}

但是,这并不能同时具有命名空间属性名称和具有相同名称的非命名空间属性。这仍然会导致:


main.Typemap field "Type" with tag "type,attr" conflicts with field "XsiType" with tag "http://www.w3.org/2001/XMLSchema-instance type,attr"

这里的解决方法是为整个Typemap类型编写一个解组器。就我而言,此代码如下所示:


func (s *Typemap) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {                                         

    nameAttr := ""                                                                                                     

    typeAttr := ""                                                                                                     

    xsiTypeAttr := ""                                                                                                  


    for _, attr := range start.Attr {                                                                                  

        if attr.Name.Space == "" && attr.Name.Local == "name" {                                                        

            nameAttr = attr.Value                                                                                      

        }                                                                                                              

        if attr.Name.Space == "" && attr.Name.Local == "type" {                                                        

            typeAttr = attr.Value                                                                                      

        }                                                                                                              

        if attr.Name.Space == "http://www.w3.org/2001/XMLSchema-instance" && attr.Name.Local == "type" {               

            xsiTypeAttr = attr.Value                                                                                   

        }                                                                                                              

    }                                                                                                                  


    d.Skip()                                                                                                           

    *s = Typemap{Name: nameAttr, Type: typeAttr, XsiType: xsiTypeAttr}                                                 


    return nil                                                                                                         

}                      


查看完整回答
反对 回复 2022-05-05
  • 1 回答
  • 0 关注
  • 215 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信