解组时将 XML 标记解析为布尔值(如果存在)

问题描述 投票:0回答:2

我正在尝试将 XML 标记解析为布尔值(如果存在)。

<status>
内的标签可以是
<active />
<available />
<invalid />
,并且
<status>
内仅存在这些标签之一。

这是我当前的尝试:

package main

import (
    "encoding/xml"
    "fmt"
)

type Response struct {
    XMLName      xml.Name `xml:"domain"`
    Authority    string   `xml:"authority,attr"`
    RegistryType string   `xml:"registryType,attr"`
    EntityClass  string   `xml:"entityClass,attr"`
    EntityName   string   `xml:"entityName,attr"`
    DomainName   string   `xml:"domainName"`
    Status       Status   `xml:"status"`
}

type Status struct {
    Active    bool `xml:"active,omitempty"`
    Available bool `xml:"available,omitempty"`
    Invalid   bool `xml:"invalid,omitempty"`
}

func main() {

    str := `
<domain authority="domain.fi" registryType="dchk1" entityClass="domain-name" entityName="esimerkki.fi">
  <domainName>esimerkki.fi</domainName>
  <status>
    <active />
  </status>
</domain>
`

    var ans Response
    err := xml.Unmarshal([]byte(str), &ans)
    if err != nil {
        panic(err)
    }

    fmt.Printf(`%#v`, ans.Status)
}

这会将所有

Status.*
返回为
false
,而不是预期的
Status.Active = true
。怎样才能达到预期的效果呢?

第二次尝试指针:

type Status struct {
    Active    *bool `xml:"active,omitempty"`
    Available *bool `xml:"available,omitempty"`
    Invalid   *bool `xml:"invalid,omitempty"`
}

*ans.Status.Active
仍然
false

xml go unmarshalling
2个回答
0
投票

正如 @mh-cbon 建议的那样,只需检查指针是否不是

nil
*bool
就足以确定该标签是否存在。但我将 XML 响应结构转换为正确的
Response
结构,其中仅包含所需的信息,并将
Status
转换为常量。

所以现在是:

// Raw XML DTO
type XmlResponse struct {
    XMLName      xml.Name  `xml:"domain"`
    Authority    string    `xml:"authority,attr"`
    RegistryType string    `xml:"registryType,attr"`
    EntityClass  string    `xml:"entityClass,attr"`
    EntityName   string    `xml:"entityName,attr"`
    DomainName   string    `xml:"domainName"`
    Status       XmlStatus `xml:"status"`
}

// Raw XML DTO
type XmlStatus struct {
    Active    *bool `xml:"active,omitempty"`
    Available *bool `xml:"available,omitempty"`
    Invalid   *bool `xml:"invalid,omitempty"`
}

// Return Response struct which doesn't have the unnecessary XML
func (x XmlResponse) GetResponse() Response {
    st := Invalid // Default to invalid

    if x.Status.Active != nil {
        st = Active
    } else if x.Status.Available != nil {
        st = Available
    } else if x.Status.Invalid != nil {
        st = Invalid
    }

    return Response{
        Domain: x.DomainName,
        Status: st,
    }
}

// Proper response parsed from XML
type Response struct {
    Domain string
    Status Status
}

type Status uint8

const (
    Invalid Status = iota
    Active
    Available
)

解析发生如下:

var xmlresp XmlResponse
err := xml.Unmarshal([]byte(str), &xmlresp)
if err != nil {
    panic(err)
}

ans := xmlresp.GetResponse()

fmt.Printf(`%#v`, ans)

0
投票

这不是一个完美的解决方案,但这是一个快速而肮脏的黑客。您可以为每个项目创建结构。

type XmlStatus struct {
    Active    Active     `xml:"active,omitempty"`
    Available Available  `xml:"available,omitempty"`
    Invalid   Invalid    `xml:"invalid,omitempty"`
}

type Active struct {
   XMLName xml.Name
}

type Available struct {
    XMLName xml.Name
}

type Invalid struct {
    XMLName xml.Name 
}

然后在后面的代码中,每个答案下面都会有一个名为 XMLName 的字段,并且该字段下会有一个名为 local 的字段。它将包含本地 xmlname。您可以使用简单的 if 语句检查该字段。即

if ans.State.Active.XMLName.Local != "" {
    // user is active 
}

有点笨拙,但它很简单并且有效。

© www.soinside.com 2019 - 2024. All rights reserved.