Golang解析XML时无法同时处理Name/name大小写敏感与不敏感的结构体问题

Golang解析XML时无法同时处理Name/name大小写敏感与不敏感的结构体问题

// 结构体
type Test struct {
    Name string              `xml:"Name,attr"`
    TestID   string              `xml:"ID",attr"`
}
<?xml version="1.0" encoding="UTF-8"?><Test Name="pankaj" TestID="12354"></Test>

或者 XML

    <?xml version="1.0" encoding="UTF-8"?><Test name="pankaj" TestID="12354"></Test>

更多关于Golang解析XML时无法同时处理Name/name大小写敏感与不敏感的结构体问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

XML 通常是区分大小写的。Go 的 XML 包实现了这一点。

更多关于Golang解析XML时无法同时处理Name/name大小写敏感与不敏感的结构体问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,使用标准库encoding/xml解析XML时,默认情况下标签匹配是大小写敏感的。这意味着结构体字段的XML标签必须与XML文档中的属性名完全一致,包括大小写。当XML文档中属性名的大小写可能变化时,这会导致解析问题。

对于您提供的结构体Test,XML标签指定了属性名NameID。如果XML文档中使用的是小写的name,则无法正确解析。标准库没有直接支持大小写不敏感的XML解析,但可以通过以下方法处理:

方法1:使用自定义UnmarshalXML方法

通过实现xml.Unmarshaler接口,可以自定义XML解析逻辑,处理大小写不敏感的情况。

package main

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

type Test struct {
    Name   string `xml:"Name,attr"`
    TestID string `xml:"ID,attr"`
}

func (t *Test) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    type Alias Test
    aux := &struct {
        *Alias
    }{
        Alias: (*Alias)(t),
    }
    
    for _, attr := range start.Attr {
        switch strings.ToLower(attr.Name.Local) {
        case "name":
            t.Name = attr.Value
        case "id":
            t.TestID = attr.Value
        }
    }
    
    return d.DecodeElement(aux, &start)
}

func main() {
    xmlData1 := `<?xml version="1.0" encoding="UTF-8"?><Test Name="pankaj" ID="12354"></Test>`
    xmlData2 := `<?xml version="1.0" encoding="UTF-8"?><Test name="pankaj" ID="12354"></Test>`
    
    var test1 Test
    if err := xml.Unmarshal([]byte(xmlData1), &test1); err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Printf("Test1: Name=%s, TestID=%s\n", test1.Name, test1.TestID)
    }
    
    var test2 Test
    if err := xml.Unmarshal([]byte(xmlData2), &test2); err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Printf("Test2: Name=%s, TestID=%s\n", test2.Name, test2.TestID)
    }
}

方法2:使用第三方库

如果标准库的限制过于严格,可以考虑使用第三方XML处理库,如libxml2的Go绑定,这些库可能提供更灵活的解析选项。

方法3:预处理XML字符串

在解析之前,将XML文档中的属性名统一转换为小写或大写,然后使用对应大小写的结构体标签。

package main

import (
    "encoding/xml"
    "fmt"
    "regexp"
    "strings"
)

type Test struct {
    Name   string `xml:"name,attr"`
    TestID string `xml:"id,attr"`
}

func normalizeXMLAttributes(xmlData string) string {
    re := regexp.MustCompile(`(\w+)=`)
    return re.ReplaceAllStringFunc(xmlData, func(m string) string {
        return strings.ToLower(m)
    })
}

func main() {
    xmlData := `<?xml version="1.0" encoding="UTF-8"?><Test Name="pankaj" ID="12354"></Test>`
    normalizedXML := normalizeXMLAttributes(xmlData)
    
    var test Test
    if err := xml.Unmarshal([]byte(normalizedXML), &test); err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Printf("Test: Name=%s, TestID=%s\n", test.Name, test.TestID)
    }
}

注意事项

  • 在自定义UnmarshalXML方法中,需要确保正确处理所有可能的属性名变体。
  • 预处理方法可能会影响性能,特别是在处理大型XML文档时。
  • 结构体定义中,TestID字段的XML标签应为xml:"ID,attr",而不是xml:"ID",attr"(注意多余的引号)。

以上方法可以解决XML属性名大小写不一致导致的解析问题。根据具体需求选择适合的方案。

回到顶部