简体   繁体   English

使用属性作为值与动态节点映射XML

[英]Map XML using attributes as value with dynamic nodes

I am attempting to convert data stored in xml documents into an alternative data store. 我正在尝试将xml文档中存储的数据转换为备用数据存储。 I have tried a variety of techniques but none have proven effective. 我尝试了多种技术,但都没有一种有效的方法。 The problem is the xml does not have a fixed schema and has an unconventional structure. 问题是xml没有固定的架构,并且具有非常规的结构。 A sample of the xml is as follows xml的示例如下

<?xml version="1.0"?>
<Data>
    <f.1 value="field value" />
    <f.2 value="other value" />
    <f.3 value="field value 2" />
    <withchildren>
        <f.3.1 value="testvalue" />
        <f.3.2 value="test value 3" />
    </withchildren>
</Data>

Ideally the end result should store the result in map[string]interface{} in order to convert the value into a standard multi-dimensional JSON format. 理想情况下,最终结果应将结果存储在map[string]interface{}中,以便将值转换为标准的多维JSON格式。

When you're unsure about the structure goquery is probably your best bet. 当您不确定结构时, goquery可能是最好的选择。 Your tag names look a little odd I assume that's just for the sample. 您的标签名称看起来有些奇怪,我认为这只是用于示例。 The code below uses the tag name for the key and uses the value attribute but you can modify it for any structure. 下面的代码使用键的标签名称并使用value属性,但是您可以为任何结构修改它。

package main

import (
    "fmt"
    "github.com/PuerkitoBio/goquery"
    "strings"
)

func main() {
    xml := `
      <?xml version="1.0"?>
      <Data>
          <f1 value="field value"></f1>
          <f2 value="other value"></f2>
          <f3 value="field value 2"></f3>
          <withchildren>
              <f31 value="testvalue"></f31>
              <f32 value="test value 3"></f32>
          </withchildren>
      </Data>
      `
    data := make(map[string]interface{})
    reader := strings.NewReader(xml)

    doc, _ := goquery.NewDocumentFromReader(reader)
    children := doc.Find("Data").Children()

    children.Each(func(i int, s *goquery.Selection) {

        val, exists := s.Attr("value")
        if exists {
            data[goquery.NodeName(s)] = val
        }

        withchildren := s.Children()

        if withchildren.Length() > 0 {
            withchildren.Each(func(i int, s *goquery.Selection) {
                val, exists := s.Attr("value")
                if exists {
                    data[goquery.NodeName(s)] = val
                }

            })
        }
    })
    fmt.Println(data)
}

And if you really have no idea what the structure could be or how many nested elements there might be try this recursive version. 而且,如果您真的不知道结构可能是什么或可能有多少嵌套元素,请尝试此递归版本。

If you have multiple elements with the same name then you could modify the code to add a number with the key name. 如果您有多个具有相同名称的元素,则可以修改代码以添加具有键名称的数字。 So "tag1", "tag2", etc. 因此,“ tag1”,“ tag2”等

package main

import (
    "github.com/PuerkitoBio/goquery"
    "strings"
)

func main() {
    xml := `
      <?xml version="1.0"?>
      <Data>
          <f1 value="field value"></f1>
          <f2 value="other value"></f2>
          <f3 value="field value 2"></f3>
          <withchildren>
              <f31 value="testvalue"></f31>
              <f32 value="test value 3"></f32>
          </withchildren>
      </Data>
      `
    data := make(map[string]interface{})
    reader := strings.NewReader(xml)

    doc, _ := goquery.NewDocumentFromReader(reader)
    children := doc.Find("Data").Children()
    data = getElements(children)
}

func getElements(children *goquery.Selection) map[string]interface{} {
    data := make(map[string]interface{})
    children.Each(func(i int, s *goquery.Selection) {
        val, exists := s.Attr("value")
        if exists {
            data[goquery.NodeName(s)] = val
        }

        if s.Children().Length() > 0 {
            data[goquery.NodeName(s)] = getElements(s.Children())
        }
    })
    return data
}

There are also some Go packages that I haven't used. 还有一些我没有使用过的Go软件包。

mxj converts xml to map[string]interface{} mxj将xml转换为map [string] interface {}

goxml2json converts from xml to json. goxml2json从xml转换为json。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM