无法通过Golang修改XML节点的值吗?

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

Can't modify the xml node value by golang?

问题

我无法修改golang中的c节点的值。我想要获取一些节点的值(可以实现),并重置一些节点的值(例如在""之间),但是出现了一些问题。如何解决?欢迎提供帮助。

以下是要翻译的代码:

package main

import (
	"fmt"
	"regexp"
)

type C struct {
	XMLName xml.Name `xml:"c"`
	V       string   `xml:"v,omitempty"`
	R       string   `xml:"r,attr"`
	T       string   `xml:"t,attr,omitempty"`
	S       string   `xml:"s,attr"`
}

type Row struct {
	XMLName xml.Name `xml:"row"`
	R       string   `xml:"r,attr"`
	C       []C      `xml:"c"`
	Spans   string   `xml:"spans,attr"`
}

type Result struct {
	XMLName xml.Name `xml:"sheetData"`
	Row     []Row    `xml:"row"`
}

func main() {
	input := `
	<sheetData>
	<row r="2" spans="1:15">
	<c r="A2" s="5" ><v>{{range .txt}}</v></c>
	<c r="B2" s="5" t="s"><v>1</v></c>
	<c r="C2" s="5" t="s"><v>2</v></c>
	<c r="D2" s="5" t="s"><v>3</v></c>
	<c r="E2" s="5" />
	<c r="K2" s="6" t="s"><v>21</v></c>
	</row> 
	<row r="3" spans="1:15">
	<c r="A3" s="5" t="s"><v>0</v></c>
	<c r="B3" s="5" t="s"><v>1</v></c>
	<c r="C3" s="5" t="s"><v>2</v></c>
	<c r="D3" s="5" t="s"><v>3</v></c>
	<c r="E3" s="5" />
	<c r="K3" s="6" t="s"><v>21</v></c>
	</row> 
	</sheetData>`

	v := Result{}
	err := xml.Unmarshal([]byte(input), &v)
	if err != nil {
		fmt.Printf("error: %v", err)
		return
	}

	for _, r := range v.Row {
		for _, c := range r.C {
			c.V = "25" //我想要设置一些c节点的值。
			fmt.Printf("%v %v %v\n", c.V, c.R, c.T)
		}
	}

	output, err := xml.MarshalIndent(&v, "", "")
	if err != nil {
		fmt.Printf("error: %v\n", err)
	}
	fmt.Println(string(output)) //但是c节点的值仍然是原始值
}

以上代码有什么问题?如何在golang中设置一些节点的值?

英文:

I can't modify the c node's value in golang. i want get the some nodes value (is ok),and reset some nodes value (such as between "<v></v>") as the following, but there are some thing wrong with it. how to do it? youe are welcome to give some help:

    package main
import (
&quot;fmt&quot;
&quot;regexp&quot;
)
type C struct {
XMLName xml.Name `xml:&quot;c&quot;`
V       string   `xml:&quot;v,omitempty&quot;`
R       string   `xml:&quot;r,attr&quot;`
T       string   `xml:&quot;t,attr,omitempty&quot;`
S       string   `xml:&quot;s,attr&quot;`
}
type Row struct {
XMLName xml.Name `xml:&quot;row&quot;`
R       string   `xml:&quot;r,attr&quot;`
C       []C      `xml:&quot;c&quot;`
Spans   string   `xml:&quot;spans,attr&quot;`
}
type Result struct {
XMLName xml.Name `xml:&quot;sheetData&quot;`
Row     []Row    `xml:&quot;row&quot;`
}
func main() {
input := `
&lt;sheetData&gt;
&lt;row r=&quot;2&quot; spans=&quot;1:15&quot;&gt;
&lt;c r=&quot;A2&quot; s=&quot;5&quot; &gt;&lt;v&gt;{{range .txt}}&lt;/v&gt;&lt;/c&gt;
&lt;c r=&quot;B2&quot; s=&quot;5&quot; t=&quot;s&quot;&gt;&lt;v&gt;1&lt;/v&gt;&lt;/c&gt;
&lt;c r=&quot;C2&quot; s=&quot;5&quot; t=&quot;s&quot;&gt;&lt;v&gt;2&lt;/v&gt;&lt;/c&gt;
&lt;c r=&quot;D2&quot; s=&quot;5&quot; t=&quot;s&quot;&gt;&lt;v&gt;3&lt;/v&gt;&lt;/c&gt;
&lt;c r=&quot;E2&quot; s=&quot;5&quot; /&gt;
&lt;c r=&quot;K2&quot; s=&quot;6&quot; t=&quot;s&quot;&gt;&lt;v&gt;21&lt;/v&gt;&lt;/c&gt;
&lt;/row&gt; 
&lt;row r=&quot;3&quot; spans=&quot;1:15&quot;&gt;
&lt;c r=&quot;A3&quot; s=&quot;5&quot; t=&quot;s&quot;&gt;&lt;v&gt;0&lt;/v&gt;&lt;/c&gt;
&lt;c r=&quot;B3&quot; s=&quot;5&quot; t=&quot;s&quot;&gt;&lt;v&gt;1&lt;/v&gt;&lt;/c&gt;
&lt;c r=&quot;C3&quot; s=&quot;5&quot; t=&quot;s&quot;&gt;&lt;v&gt;2&lt;/v&gt;&lt;/c&gt;
&lt;c r=&quot;D3&quot; s=&quot;5&quot; t=&quot;s&quot;&gt;&lt;v&gt;3&lt;/v&gt;&lt;/c&gt;
&lt;c r=&quot;E3&quot; s=&quot;5&quot; /&gt;
&lt;c r=&quot;K3&quot; s=&quot;6&quot; t=&quot;s&quot;&gt;&lt;v&gt;21&lt;/v&gt;&lt;/c&gt;
&lt;/row&gt; 
&lt;/sheetData&gt;`
v := Result{}
err := xml.Unmarshal([]byte(input), &amp;v)
if err != nil {
fmt.Printf(&quot;error: %v&quot;, err)
return
}
for _, r := range v.Row {
for _, c := range r.C {       
c.V=&quot;25&quot;          //i want the set some c node value.
fmt.Printf(&quot;%v %v %v\n&quot;, c.V, c.R,c.T)
}
}
output, err := xml.MarshalIndent(&amp;v, &quot;&quot;, &quot;&quot;)
if  err != nil {
fmt.Printf(&quot;error: %v\n&quot;, err)
} 
fmt.Println(string(output))   //but the c node value is still original
}          
}  

What wrong with the above? how to set some node valule in golang?

答案1

得分: 4

这是一个可工作的示例(使用缩进表示XML):Playground

解释:

你在for循环中复制了你的结构体。
当写成

for _, r := range v.Row {

rv.Row 中值的副本
如果你试图改变这个值,你只会改变副本,而原始值不会改变。

你应该像这样编写你的循环

for i := range v.Row {

并通过 v.Row[i] 访问结构体。

对于内部循环也是一样的,应该像这样编写:

for j := range v.Row[i].C {

然后你可以像这样改变列:

v.Row[i].C[j].V = "25"

可选地,你可以通过写 c := &v.Row[i].C[j] 来获取对列的引用,然后像 c.V = "25" 这样改变值。

英文:

Here's a working example (using identation for XML): Playground

Explanation:

You're copying your structs in your for-loop.
When writing

for _, r := range v.Row {

r is a copy of the value(s) in v.Row.
If you then try to change the value, you will just change the copy, but the original value won't change.

You should write your loop like

for i := range v.Row {

and access the struct with v.Row[i] instead.

The same applies to your inner loop, which should be written like this:

for j := range v.Row[i].C {

Then you can change the column like

v.Row[i].C[j].V = &quot;25&quot;

Optionally you could get a reference to the column by writing c := &amp;v.Row[i].C[j] and then change values as c.V = &quot;25&quot;

huangapple
  • 本文由 发表于 2015年1月20日 16:14:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/28040448.html
匿名

发表评论

匿名网友

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

确定