XML unmarshalling in Golang

huangapple go评论74阅读模式
英文:

XML unmarshalling in Golang

问题

我想将以下 XML 负载解组为结构体:

<linearPackagePublish>
    <linearPackage>
        <name>ABC</name>
        <packagedServiceReference>
            <availabilityWindowEnd>2329-12-31 23:59:59</availabilityWindowEnd>
            <availabilityWindowStart>2007-11-14 11:40:00</availabilityWindowStart>
            <packagedServiceId>1111111111</packagedServiceId>
        </packagedServiceReference>
        <partnerPackageId>XXXXXXX</partnerPackageId>
    </linearPackage>
    <partnerId>XXXXXX</partnerId>
    <wantLinearPublishResult>true</wantLinearPublishResult>
</linearPackagePublish>

我想在 <wantLinearPublishResult> 标签之前添加 transactionId,如下所示:

<linearPackagePublish>
    <linearPackage>
        <name>ABC</name>
        <packagedServiceReference>
            <availabilityWindowEnd>2329-12-31 23:59:59</availabilityWindowEnd>
            <availabilityWindowStart>2007-11-14 11:40:00</availabilityWindowStart>
            <packagedServiceId>1111111111</packagedServiceId>
        </packagedServiceReference>
        <partnerPackageId>XXXXXXX</partnerPackageId>
    </linearPackage>
    <partnerId>XXXXXX</partnerId>
    <transactionId>111111111111</transactionId>
    <wantLinearPublishResult>true</wantLinearPublishResult>
</linearPackagePublish>

为此,我尝试将上述 XML 解组为以下结构体:

type linearPackagePublish struct {
    LinearPackage           string `xml:"linearPackage"`
    MsoPartnerID            string `xml:"partnerId"`
    TransactionID           string `xml:"transactionId,omitempty"`
    WantLinearPublishResult bool   `xml:"wantLinearPublishResult,omitempty"`
}

但问题是,我不想解组 linearPackage 元素,所以我在结构体中将 LinearPackage 设置为字符串。

我也可以使用正则表达式来实现,但如果 XML 发生变化,这种方法会更容易出错。

有没有办法将某些嵌套的 XML 元素作为字符串处理?

英文:

I want to unmarshall the below xml payload to struct

&lt;linearPackagePublish&gt;
                &lt;linearPackage&gt;
                    &lt;name&gt;ABC&lt;/name&gt;
                    &lt;packagedServiceReference&gt;
                        &lt;availabilityWindowEnd&gt;2329-12-31 23:59:59&lt;/availabilityWindowEnd&gt;
                        &lt;availabilityWindowStart&gt;2007-11-14 11:40:00&lt;/availabilityWindowStart&gt;
                        &lt;packagedServiceId&gt;1111111111&lt;/packagedServiceId&gt;
                    &lt;/packagedServiceReference&gt;
                    &lt;partnerPackageId&gt;XXXXXXX&lt;/partnerPackageId&gt;
                &lt;/linearPackage&gt;
                &lt;partnerId&gt;XXXXXX&lt;/partnerId&gt;
                &lt;wantLinearPublishResult&gt;true&lt;/wantLinearPublishResult&gt;
            &lt;/linearPackagePublish&gt;

I want to add transactionId just before <wantLinearPublishResult> tag like this:

&lt;linearPackagePublish&gt;
                &lt;linearPackage&gt;
                    &lt;name&gt;ABC&lt;/name&gt;
                    &lt;packagedServiceReference&gt;
                        &lt;availabilityWindowEnd&gt;2329-12-31 23:59:59&lt;/availabilityWindowEnd&gt;
                        &lt;availabilityWindowStart&gt;2007-11-14 11:40:00&lt;/availabilityWindowStart&gt;
                        &lt;packagedServiceId&gt;1111111111&lt;/packagedServiceId&gt;
                    &lt;/packagedServiceReference&gt;
                    &lt;partnerPackageId&gt;XXXXXXX&lt;/partnerPackageId&gt;
                &lt;/linearPackage&gt;
                &lt;partnerId&gt;XXXXXX&lt;/partnerId&gt;
		&lt;transactionId&gt;111111111111&lt;/transactionId&gt;
                &lt;wantLinearPublishResult&gt;true&lt;/wantLinearPublishResult&gt;
            &lt;/linearPackagePublish&gt;

For this purpose I was trying to unmarshall the above xml to below struct:

type linearPackagePublish struct {
    LinearPackage           string `xml:&quot;linearPackage&quot;`
    MsoPartnerID            string `xml:&quot;partnerId&quot;`
    TransactionID           string `xml:&quot;transactionId,omitempty&quot;`
    WantLinearPublishResult bool   `xml:&quot;wantLinearPublishResult,omitempty&quot;`
}

But the thing is I don’t want to unmarshall the linearPackage element that is why I put LinearPackage as string in struct

I can also do it via regex but it will be more error prone if something change in the xml.

Is there any way that we can make some nested xml element as a string??

答案1

得分: 1

你可以定义一个自定义类型,其中包含自己定义的marshal和unmarshal函数,而不是尝试使用字符串。这样你就可以直接控制该元素。

你可以看到自定义数据类型包含一个xml.Tokens数组。这个数组在解组过程中被填充,然后在编组过程中写入编码器。

type skipUnmarshal struct {
    data []xml.Token
}

func (s skipUnmarshal) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
    for i := 0; i < len(s.data); i++ {
        e.EncodeToken(s.data[i])
    }
    return nil
}

func (s *skipUnmarshal) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    for {
        t, err := d.Token()
        if err != nil {
            break // or alternatively return the error
        }
        s.data = append(s.data, t)
    }
    return nil
}

你可以在Go Playground上看到一个工作示例。

英文:

Edited to provide more detail. Including a working demo on Go Playground

Rather than trying to use a string you can define a custom type, with its own marshal and unmarshal functions defined. That way you can have direct control over that element.

You can see the custom datatype holds an array of xml.Tokens. This array is populated during unmarshalling and then written to the encoder during marshalling.

type skipUnmarshal struct {
    data []xml.Token
}

func (s skipUnmarshal) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
    for i := 0; i &lt; len(s.data); i++ {
	    e.EncodeToken(s.data[i])
    }
	return nil
}
func (s *skipUnmarshal) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	for {
    	t, err := d.Token()
	    if err != nil {
		    break // or alternatively return the error
	    }
	    s.data = append(s.data, t)
    }
    return nil
}

huangapple
  • 本文由 发表于 2022年7月21日 15:28:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/73062234.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定