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

正确编组和解组包含 xmlns:wcm 和 xmlns:xsi 的 XML

正确编组和解组包含 xmlns:wcm 和 xmlns:xsi 的 XML

Go
炎炎设计 2023-03-07 17:31:50
我正在尝试处理 Windows Autounattend.xml 文件的读写,以便创建和修改它们。我无法获取xmlns:wcm和xmlns:xsi正确编组和解组属性。我正在尝试处理 Windows Autounattend.xml 文件的读写,以便创建和修改它们。我无法获取xmlns:wcm和xmlns:xsi正确编组和解组属性。
查看完整描述

1 回答

?
眼眸繁星

TA贡献1873条经验 获得超9个赞

xmlns:wcmxmlns:xsi不是真正的属性,它们是经过特殊处理的。您的 XML 既没有元素也没有来自wcmxsi模式的属性,它们将被删除。为什么你的代码中需要它们?

不过,如果您真的非常需要它们,您可以将以下字段添加到结构中Component

    Attr                  []xml.Attr `xml:",any,attr"`

xml.Unmarshal文件说

如果 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:wcmxmlns:xsi不承担任何业务逻辑。他们没有提供有关设置和组件的信息。你真的需要它们吗?

注 3. 绝对没有要求命名这些属性xmlns:wcmxmlns: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:statehttp://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>


查看完整回答
反对 回复 2023-03-07
  • 1 回答
  • 0 关注
  • 152 浏览
慕课专栏
更多

添加回答

举报

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