xml - 在两个命名空间中解组具有相同属性名称的 XML 属性
问题描述
我有一个 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 main
import (
"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
属性?
我也设置了一个围棋游乐场
解决方案
事实证明,目前没有办法在 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
}
推荐阅读
- python - 有没有办法分析一个文本文件来检查这个标准
- sql - Oracle PL SQL 过程需要修改以接受具有所有类型字符的数组并拆分
- laravel - Laravel - AWS s3 无法连接
- splunk - Splunk 查询 - 从具有计数的日志中搜索唯一异常
- aggregate - R functions re-usability
- soap - Apache Camel 调用 SOAP 服务
- http - 如何在不停止的情况下导出 tshark 对象
- mysql - MYSQL (Mac) - 无法连接,服务器可能没有运行
- swift - 如何防止在状态更改swiftUI中刷新其他视图
- python - 有人能解释一下这段代码片段中 ResNet50 的负责人是如何变化的吗?