如何使用 Go 和 etree XML 包访问同级元素?

问题描述 投票:0回答:1

给定一个如下所示的 XML 文档:

<MasterXML>
    <Processes>
        <Params>
            <ParamName>today</ParamName>
            <ParamType>1</ParamType>
            <ParamValue/>
        </Params>
       <Params>
            <ParamName>today</ParamName>
            <ParamType>2</ParamType>
            <ParamValue/>
        </Params>
       <Params>
            <ParamName>today</ParamName>
            <ParamType>3</ParamType>
            <ParamValue/>
        </Params>
    </Processes>
</MasterXML>

使用 beevik/etree for Go 包,当

<ParamValue/>
具有特定的特定值时,如何访问文档中
<Params>
的每个实例的
<ParamName>
,以用值填充它。

在给定的示例中,当

<ParamValue/>
持有值
today 时,我希望用 05/02/2024
 填充所有 <Params> 节点中的所有 <ParamName> 节点。

此代码仅适用于包含许多实例的文档中

<Params>
节点的第一个实例,其中
<ParamName>
== today ,尽管循环似乎应该访问
<Params>
的每个实例:

    for _, elem1 := range doc.FindElements(".//Processes//Params//ParamName") {
    
            if elem1 == nil {
                log.Fatal("Check XPath)
            }
    
            s := elem1.Text()
    
            if s == "today" {
                elem2 := elem1.FindElement("//ParamValue")
                elem2.SetText("05/02/2024")
            }
    }

我该怎么做?为什么

range doc.FindElements(".//Processes//Params//ParamName")
找不到
<Params>
的每个实例?我应该使用不同的方法吗?

xml go siblings go.etree
1个回答
0
投票

您当前的代码确实按照您所描述的方式运行,因为通过在 XPath 中使用双斜杠,您始终以递归方式搜索 XML 树,这意味着您始终从顶部找到第一个出现的位置。

这是固定样本:

package main

import (
    "log"
    "os"
    "strings"

    "github.com/beevik/etree"
)

func main() {
    doc := etree.NewDocument()
    if err := doc.ReadFromFile("master.xml"); err != nil {
        panic(err)
    }

    for _, elem1 := range doc.FindElements(".//Processes//Params//ParamName") {

        if elem1 == nil {
            log.Fatal("Check XPath")
        }

        s := elem1.Text()
        //println(s)

        if strings.TrimSpace(s) == "today" {
            elem2 := elem1.FindElement("../ParamValue")
            elem2.SetText("05/02/2024")
        }
    }

    doc.WriteTo(os.Stdout)
}

这需要

master.xml
与您的
.go
文件位于同一目录中。我选择了这个:

<MasterXML>
    <Processes>
        <Params>
            <ParamName> today </ParamName>
            <ParamType>1</ParamType>
            <ParamValue/>
        </Params>
       <Params>
            <ParamName> tomorrow </ParamName>
            <ParamType>2</ParamType>
            <ParamValue/>
        </Params>
       <Params>
            <ParamName> today </ParamName>
            <ParamType>3</ParamType>
            <ParamValue/>
        </Params>
    </Processes>
</MasterXML>

产生所需的输出:

<MasterXML>
    <Processes>
        <Params>
            <ParamName> today </ParamName>
            <ParamType>1</ParamType>
            <ParamValue>05/02/2024</ParamValue>
        </Params>
       <Params>
            <ParamName> tomorrow </ParamName>
            <ParamType>2</ParamType>
            <ParamValue/>
        </Params>
       <Params>
            <ParamName> today </ParamName>
            <ParamType>3</ParamType>
            <ParamValue>05/02/2024</ParamValue>
        </Params>
    </Processes>
</MasterXML>
© www.soinside.com 2019 - 2024. All rights reserved.