Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何封送和取消封送具有不规则属性的XML_Xml_Go_Attributes_Marshalling_Unmarshalling - Fatal编程技术网

如何封送和取消封送具有不规则属性的XML

如何封送和取消封送具有不规则属性的XML,xml,go,attributes,marshalling,unmarshalling,Xml,Go,Attributes,Marshalling,Unmarshalling,我有一个XML,其中不同的实体用相同的标记表示,但属性不同。大概是这样的: 保证每种类型只有一个数据包 不幸的是,改变XML的结构不是我的责任,我必须按原样处理它。在Go中处理此类结构的最佳方法是什么?我是否应该拥有一个包含所有可能属性的结构,并为每个“数据包”填充正确的属性 类型XML结构{ XMLName xml.Name`xml:“xml”` 身体结构{ 数据包[]结构{ 类型字符串`xml:“类型,属性”` 行[]结构{ ID字符串`xml:“ID,attr”` 名称字符串`xml:

我有一个XML,其中不同的实体用相同的标记表示,但属性不同。大概是这样的:


保证每种类型只有一个数据包

不幸的是,改变XML的结构不是我的责任,我必须按原样处理它。在Go中处理此类结构的最佳方法是什么?我是否应该拥有一个包含所有可能属性的结构,并为每个“数据包”填充正确的属性

类型XML结构{
XMLName xml.Name`xml:“xml”`
身体结构{
数据包[]结构{
类型字符串`xml:“类型,属性”`
行[]结构{
ID字符串`xml:“ID,attr”`
名称字符串`xml:“名称,属性”`
Sum字符串`xml:“Sum,attr”`
状态字符串`xml:“状态,属性”`
}`xml:“行”`
}`xml:“数据包”`
}`xml:“正文”`
} 
这似乎是可行的,但相当不方便,因为在现实中,我有很多不同类型的数据包,具有不同属性的负载

或者有办法将数据包映射到不同的Go结构?大概是这样的:

类型XML结构{
XMLName xml.Name`xml:“xml”`
身体结构{
ClientPacket结构{
类型字符串`xml:“类型,属性”`
行[]结构{
ID字符串`xml:“ID,attr”`
名称字符串`xml:“名称,属性”`
}`xml:“行”`
}`xml:'Packet`/???
OrderPacket结构{
类型字符串`xml:“类型,属性”`
行[]结构{
Sum字符串`xml:“Sum,attr”`
状态字符串`xml:“状态,属性”`
}`xml:“行”`
}`xml:'Packet`/???
}`xml:“正文”`
} 

后者看起来更聪明、可读性更强,但我不知道如何使用它封送和解封xml

我可以想出几种方法来实现这一点:您可以尝试前面描述的方法,使用包含所有可能属性的结构。这将是乏味但容易的。您还可以尝试为
数据包
编写自定义解组器:

type PacketXML struct {
   A *PacketTypeA
   B *PacketTypeB
   ...
}

func (x *PacketXML)  UnmarshalXML(d *Decoder, start StartElement) error {
    // Look at start attributes, find out what type of packet it has
    packetType:=findAttr(start,"type")
    switch packetType {
      case "typeA":
         x.A=&PacketTypeA{}
         return d.Decode(x.A)
      case "typeB":
         x.B=&PacketTypeB{}
         return d.Decode(x.B)
      ...
    }
  return nil
}

完成所有操作后,您可以检查
PacketXML
实例的哪个元素是非nill,并使用它。

在编组之前首先转换文件(例如使用XSLT)。

您可以尝试“检测”您拥有的数据类型和Marshmall以不同的方式进行封送,我最终使用了这个库,它提供了对结果XML的所有控制:以及每个“数据包”的单独结构(但使用相同的接口包装)。从结构到xmlwriter类型的转换可以通过反射完成,也可以不通过反射完成(对于每个结构)。