如何在动态 XML 中使用 Golang 获取 XML 前缀而不使用结构体?

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

How to get xml prefix in golang in dynamic xml without struct

问题

假设我有这样的XML:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.opentravel.org/OTA/2003/05">
    <soap:Header/>
    <soap:Body>
        <contents>
            <article>
                <category>Server</category>
                <title>Connect to Oracle Server using Golang and Go-OCI8 on Ubuntu</title>
                <url>/go-oci8-oracle-linux/</url>
            </article>
            <!-- ... -->
        </contents>
    </soap:Body>
</soap:Envelope>

我还有这样的常见结构体:

type envelope struct {
	XMLName xml.Name
	Attrs   []xml.Attr `xml:",any,attr"`
	Body    struct {
		InnerXML []byte `xml:",innerxml"`
	}
}

问题是如何获取最外层包装器中的 soap(来自 soap:Envelope)这个词。

英文:

Suppose I have an XML like this

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.opentravel.org/OTA/2003/05">
    <soap:Header/>
    <soap:Body>
        <contents>
            <article>
                <category>Server</category>
                <title>Connect to Oracle Server using Golang and Go-OCI8 on Ubuntu</title>
                <url>/go-oci8-oracle-linux/</url>
            </article>
            <!-- ... -->
        </contents>
    </soap:Body>
</soap:Envelope>

I also have common struct like this

type envelope struct {
	XMLName xml.Name
	Attrs   []xml.Attr `xml:",any,attr"`
	Body    struct {
		InnerXML []byte `xml:",innerxml"`
	}
}

The problem is how to get the word soap (from soap:Envelope)in the most outer wrapper

答案1

得分: 1

我不确定这个解决方案的限制,如果有的话,请在评论中指出。

  1. 您可以直接使用结构体来捕获根节点的前缀URI。
  2. 获取属性的切片,每个属性都有一个将URI映射到前缀名称的结构体。
  3. 遍历属性,并尝试将每个属性的值与节点的前缀URI进行匹配,然后
  4. 保存属性的本地名称和前缀的名称。

(我认为这一切都是有道理的,我用正确的名称调用了正确的东西)

以下是代码示例:

var e envelope
xml.Unmarshal(data, &e)

var rootURI, rootPrefix string

rootURI = e.XMLName.Space
for _, attr := range e.Attrs {
	if attr.Name.Space == "xmlns" && attr.Value == rootURI {
		rootPrefix = attr.Name.Local
		break
	}
}

fmt.Println(rootPrefix, rootURI)

当我使用您的示例XML运行该代码时,输出结果为:

soap http://schemas.xmlsoap.org/soap/envelope/

这是完整的演示,点击此处查看

英文:

I'm not sure of the limitations of this solution; please kindly point them out in the comments.

  1. You can use your struct as is to capture the root node's prefix URI
  2. get the slice of attributes, each of which has a struct that maps a URI to a name for the prefix
  3. iterate the attributes and try to match each attribute's value to the node's prefix URI, then
  4. save the attribute's local name, the name of the prefix

(I think that all makes sense, I called the right things by the right names)

Here's what it looks like:

var e envelope
xml.Unmarshal(data, &e)

var rootURI, rootPrefix string

rootURI = e.XMLName.Space
for _, attr := range e.Attrs {
	if attr.Name.Space == "xmlns" && attr.Value == rootURI {
		rootPrefix = attr.Name.Local
		break
	}
}

fmt.Println(rootPrefix, rootURI)

When I run that with your sample XML, it prints:

soap http://schemas.xmlsoap.org/soap/envelope/

Here's the complete demo, <https://go.dev/play/p/x3FKfkCW64x>.

答案2

得分: 0

我找到了一个名为https://github.com/beevik/etree的golang库,所以我的代码将会是这样的:

func getPrefix(xmlbytes []byte) string {
	doc := etree.NewDocument()

	if err := doc.ReadFromBytes(xmlbytes); err != nil {
		log.Fatal(err.Error())
	}

	return doc.Root().Space
}
英文:

I found a golang library that is called https://github.com/beevik/etree so my code will be like this

func getPrefix(xmlbytes []byte) string {
	doc := etree.NewDocument()

	if err := doc.ReadFromBytes(xmlbytes); err != nil {
		log.Fatal(err.Error())
	}

	return doc.Root().Space
}

huangapple
  • 本文由 发表于 2022年10月3日 12:01:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/73931009.html
匿名

发表评论

匿名网友

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

确定