1 回答
TA贡献1873条经验 获得超9个赞
xmlns:wcm
而xmlns:xsi
不是真正的属性,它们是经过特殊处理的。您的 XML 既没有元素也没有来自wcm
和xsi
模式的属性,它们将被删除。为什么你的代码中需要它们?
不过,如果您真的非常需要它们,您可以将以下字段添加到结构中Component
:
Attr []xml.Attr `xml:",any,attr"`
如果 XML 元素具有先前规则未处理的属性,并且结构具有包含“,any,attr”的关联标记的字段,则 Unmarshal 会在第一个此类字段中记录属性值。
这是一个例子:https://go.dev/play/p/tGDh5Ay1kZW
func main() {
var u Unattend
err := xml.Unmarshal([]byte(document), &u)
if err != nil {
log.Fatal(err)
}
for _, a := range u.Settings[0].Components[0].Attr {
fmt.Printf("Unmatched attributes: %s:%s = %s\n", a.Name.Space, a.Name.Local, a.Value)
}
}
输出:
Unmatched attributes: xmlns:wcm = http://schemas.microsoft.com/WMIConfig/2002/State
Unmatched attributes: xmlns:xsi = http://www.w3.org/2001/XMLSchema-instance
注意 1. 这个解决方案不太好的地方:它只处理额外的属性<component/>
。但是xmlns:XXX
属性可以出现在任何元素中。在一般情况下,您应该Attr
在数据模型的所有结构中添加数组。
注2. 属性xmlns:wcm
和xmlns:xsi
不承担任何业务逻辑。他们没有提供有关设置和组件的信息。你真的需要它们吗?
注 3. 绝对没有要求命名这些属性xmlns:wcm
和xmlns:xsi
. 这只是一种常见的做法。XML 文档可以命名它们xmlns:foo
并且xmlns:bar
- 它是完全有效的。连价值观"http://schemas.microsoft.com/WMIConfig/2002/State"
都没"http://www.w3.org/2001/XMLSchema-instance"
有意义。它们可以是任何字符串,唯一的要求是匹配URI 格式。例如urn:microsoft:wmi-config:2002:state
与http://schemas.microsoft.com/WMIConfig/2002/State
解析这些属性Component
非常具体,可能会在其他有效的 XML 文档上失败,这些文档在其他元素中或使用其他后缀或值声明这些属性。
更新
编组工作不如预期。xml.Marshal
专门处理xmlns
名称空间并转换Attr
为名称空间xmlns:wcm
并转换xmlns:xsi
为名称空间_xmlns
<component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:_xmlns="xmlns" _xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" _xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
</component>
解决方法是为属性使用特殊类型:
type XMLNSAttr struct {
Name xml.Name
Value string
}
func (a XMLNSAttr) Label() string {
if a.Name.Space == "" {
return a.Name.Local
}
if a.Name.Local == "" {
return a.Name.Space
}
return a.Name.Space + ":" + a.Name.Local
}
func (a *XMLNSAttr) UnmarshalXMLAttr(attr xml.Attr) error {
a.Name = attr.Name
a.Value = attr.Value
return nil
}
func (a XMLNSAttr) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
return xml.Attr{
Name: xml.Name{
Space: "",
Local: a.Label(),
},
Value: a.Value,
}, nil
这种类型通过构造一个将命名空间嵌入到本地名称中的属性来达到目的。场
Attr []xml.Attr `xml:",any,attr"`
正确解码/编码xmlns:xxx
属性
示例: https: //go.dev/play/p/VDofREl5nf1
输出:
Unmatched attributes: xmlns:wcm = http://schemas.microsoft.com/WMIConfig/2002/State
Unmatched attributes: xmlns:xsi = http://www.w3.org/2001/XMLSchema-instance
<unattend>
<settings pass="windowsPE">
<component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
</component>
...
</settings>
</unattend>
- 1 回答
- 0 关注
- 152 浏览
添加回答
举报