英文:
How do I retain the outer XML of sub-elements?
问题
我有一个包含一系列<order/>
元素的XML文件。我想将这个单一的XML文件拆分成多个文件,每个文件包含一个单独的订单。
示例输入文件:
<!-- language: lang-xml -->
<orders>
<order order-id="123">
<line-item product-id="ABC">ABC</line-item>
</order>
<order order-id="456">
<line-item product-id="DEF">DEF</line-item>
</order>
</orders>
期望的输出:
Order-123.xml:
<order order-id="123">
<line-item product-id="ABC">ABC</line-item>
</order>
Order-456.xml:
<order order-id="456">
<line-item product-id="DEF">DEF</line-item>
</order>
在这个阶段,我不关心将每个订单详细信息解组成结构体;我只想要每个<order/>
节点的精确副本。
我尝试了一些使用xml:",innerxml"
的变体,像这样:
<!-- language: lang-golang -->
type OrdersRaw struct {
Orders []OrderRaw `xml:"order"`
}
type OrderRaw struct {
Order string `xml:",innerxml"`
}
上面的代码中的问题是,每个Order
值包含内部XML(从<line-item/>
开始),但不包含包装的<order/>
标签。
理想情况下,如果有一个xml:",outerxml"
标签,它将满足我的需求。
我试图避免像手动连接内部XML和手写XML(例如<order order-id="123">
)这样的笨拙方法。
英文:
I have an XML file that contains a list of individual <order/>
elements. I would like to split this single XML file up into multiple files, each of which contain a single order.
Example input file:
<!-- language: lang-xml -->
<orders>
<order order-id="123">
<line-item product-id="ABC">ABC</line-item>
</order>
<order order-id="456">
<line-item product-id="DEF">DEF</line-item>
</order>
</orders>
Desired outputs:
> Order-123.xml:
>
> <order order-id="123">
> <line-item product-id="ABC">ABC</line-item>
> </order>
>
> Order-456.xml:
>
> <order order-id="456">
> <line-item product-id="DEF">DEF</line-item>
> </order>
At this stage, I am not concerned with unmarshalling each of the order details into a struct; I merely want an exact copy of each <order/>
node in its own file.
I have tried a few variations of this using xml:",innerxml"
, like this:
<!-- language: lang-golang -->
type OrdersRaw struct {
Orders []OrderRaw `xml:"order"`
}
type OrderRaw struct {
Order string `xml:",innerxml"`
}
The problem in the above code is that each Order
value contains the inner XML (starting with <line-item/>
) but does not contain the wrapping <order/>
tag.
Ideally, if there were an xml:",outerxml"
tag, it would serve my purpose.
I am trying to avoid doing hacky things like manually concatenating the inner XML with handwritten XML (e.g. <order order-id="123">
).
答案1
得分: 2
在你的OrderRaw
结构体上使用XMLName
:
type OrderRaw struct {
XMLName xml.Name `xml:"order"`
Order string `xml:",innerxml"`
OrderID string `xml:"order-id,attr"`
}
Playground: https://play.golang.org/p/onK5FExqzD.
**编辑:**如果你想保存所有属性,你需要使用MarshalerXML
和UnmarshalerXML
接口:
func (o *OrderRaw) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
o.attrs = map[xml.Name]string{}
for _, a := range start.Attr {
o.attrs[a.Name] = a.Value
}
type order OrderRaw
return d.DecodeElement((*order)(o), &start)
}
func (o OrderRaw) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
for name, attr := range o.attrs {
start.Attr = append(start.Attr, xml.Attr{Name: name, Value: attr})
}
start.Name = xml.Name{Local: "order"}
type order OrderRaw
return e.EncodeElement(order(o), start)
}
Playground: https://play.golang.org/p/XhkwqJFyMd.
英文:
Use XMLName
on your OrderRaw
:
type OrderRaw struct {
XMLName xml.Name `xml:"order"`
Order string `xml:",innerxml"`
OrderID string `xml:"order-id,attr"`
}
Playground: https://play.golang.org/p/onK5FExqzD.
EDIT: If you want to save all attributes, you'll have to use MarshalerXML
and UnmarshalerXML
interfaces:
func (o *OrderRaw) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
o.attrs = map[xml.Name]string{}
for _, a := range start.Attr {
o.attrs[a.Name] = a.Value
}
type order OrderRaw
return d.DecodeElement((*order)(o), &start)
}
func (o OrderRaw) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
for name, attr := range o.attrs {
start.Attr = append(start.Attr, xml.Attr{Name: name, Value: attr})
}
start.Name = xml.Name{Local: "order"}
type order OrderRaw
return e.EncodeElement(order(o), start)
}
Playground: https://play.golang.org/p/XhkwqJFyMd.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论