如何在不使用结构体的情况下,使用 Golang 从 XML 文档中删除/修改 XML 元素?

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

How to remove/delete/modify XML elements from an XML document using Golang without using structs

问题

我正在使用Golang编写一个API网关,我们需要从文档中删除特定的XML元素。

由于XML结构庞大且可变,我们无法使用结构体/编组,但我们需要根据名称/路径删除一些XML元素。

我尝试了对XML文档进行“遍历”,并根据名称“跳过”某些元素。

这是我的示例代码,但是我遇到了错误:https://go.dev/play/p/LJtlYXWvJ_d

panic: xml: end tag </age> does not match start tag <person>

我一定做错了什么,而且我找到的大多数示例都使用结构体来实现这一点。

英文:

I am using Golang for an API gateway and we need to remove certain XML elements from documents.

We are unable to use structs/marshalling as the XML structures are huge and variable - but we consistently need to remove a few XML elements based on their name/path

I have tried to "walk" the XML document and "skip" certain elements based on their name.

My example is here, but I am getting errors: https://go.dev/play/p/LJtlYXWvJ_d

panic: xml: end tag &lt;/age&gt; does not match start tag &lt;person&gt;

I must be doing something wrong, and most examples I can find use Structs to do this.

答案1

得分: 1

如果你看这个输出:

End Tag of  age  parent name is  age

它给了一个很好的线索。然后看这里:

		case xml.EndElement:
			println("End Tag of ", t.Name.Local, " parent name is ", parent.Name.Local)
			if skip && t.Name == parent.Name {
				skip = false
				parent = xml.StartElement{}
			}
			if !skip {
				println("Encoding End Element ", t.Name.Local, " buffer is ", buf.String())
				err := encoder.EncodeToken(token)
				if err != nil {
					panic(err)
				}
			}
			encoder.Flush()

从输出中我们可以看到 skip && t.Name == parent.Name 将为真。我们将 skip 切换为 false 并重置 parent。然后我们继续检查 if !skip。我们刚刚将 skip 设置为 false,所以我们尝试对该令牌进行编码。但我们应该跳过该令牌!

修复方法很简单:只需在该 case 条件中添加一个 break

			if skip && t.Name == parent.Name {

				skip = false
				parent = xml.StartElement{}
				break
			}

给出(已删除调试输出):

		&lt;people&gt;
			&lt;person&gt;
				&lt;name&gt;John&lt;/name&gt;
			&lt;/person&gt;
			&lt;person&gt;
				&lt;name&gt;Jane&lt;/name&gt;
			&lt;/person&gt;
		&lt;/people&gt;
英文:

If you look at this output:

End Tag of  age  parent name is  age

It gives a good clue. Then look right here:

		case xml.EndElement:
			println(&quot;End Tag of &quot;, t.Name.Local, &quot; parent name is &quot;, parent.Name.Local)
			if skip &amp;&amp; t.Name == parent.Name {
				skip = false
				parent = xml.StartElement{}
			}
			if !skip {
				println(&quot;Encoding End Element &quot;, t.Name.Local, &quot; buffer is &quot;, buf.String())
				err := encoder.EncodeToken(token)
				if err != nil {
					panic(err)
				}
			}
			encoder.Flush()

From the output we can see that skip &amp;&amp; t.Name == parent.Name will be true. We toggle skip to be false and reset parent. Then we proceed to check if !skip . We just set skip to false, so we attempt to encode the token. But we were supposed to skip that token!

The fix is simple: just add a break to that case condition.

			if skip &amp;&amp; t.Name == parent.Name {

				skip = false
				parent = xml.StartElement{}
				break
			}

gives (debugging output removed):

&amp;#x9;&amp;#x9;&lt;people&gt;
&amp;#x9;&amp;#x9;&amp;#x9;&lt;person&gt;
&amp;#x9;&amp;#x9;&amp;#x9;&amp;#x9;&lt;name&gt;John&lt;/name&gt;
&amp;#x9;&amp;#x9;&amp;#x9;&amp;#x9;
&amp;#x9;&amp;#x9;&amp;#x9;&lt;/person&gt;
&amp;#x9;&amp;#x9;&amp;#x9;&lt;person&gt;
&amp;#x9;&amp;#x9;&amp;#x9;&amp;#x9;&lt;name&gt;Jane&lt;/name&gt;
&amp;#x9;&amp;#x9;&amp;#x9;&amp;#x9;
&amp;#x9;&amp;#x9;&amp;#x9;&lt;/person&gt;
&amp;#x9;&amp;#x9;&lt;/people&gt;

huangapple
  • 本文由 发表于 2023年4月17日 22:21:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76036166.html
匿名

发表评论

匿名网友

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

确定