Туда и обратно xml через UnMarshal и MarshalIndent - PullRequest
0 голосов
/ 05 октября 2018

Я хотел быстро создать утилиту для форматирования любых XML-данных, используя xml.MarshalIndent () golang *)

Однако этот код

package main

import (
    "encoding/xml"
    "fmt"
)

func main() {

    type node struct {
        XMLName  xml.Name
        Attrs    []xml.Attr `xml:",attr"`
        Text     string     `xml:",chardata"`
        Children []node     `xml:",any"`
    }

    x := node{}
    _ = xml.Unmarshal([]byte(doc), &x)
    buf, _ := xml.MarshalIndent(x, "", "  ") // prefix, indent

    fmt.Println(string(buf))
}

const doc string = `<book lang="en">
     <title>The old man and the sea</title>
       <author>Hemingway</author>
</book>`

Производит

<book>&#xA;     &#xA;       &#xA;
  <title>The old man and the sea</title>
  <author>Hemingway</author>
</book>

Обратите внимание на постороннюю материю после <book> открывающего элемента.

  • Я потерял свои атрибуты - почему?
  • Я бы хотел избежать сбора ложногомежэлементное чардата - Как?

1 Ответ

0 голосов
/ 05 октября 2018

Для начала, вы не правильно используете тег структуры атрибута, так что это простое исправление.

С https://godoc.org/encoding/xml#Unmarshal

  • Если XMLэлемент имеет атрибут, который не обрабатывается предыдущим правилом, а структура имеет поле со связанным тегом, содержащим «, any, attr», Unmarshal записывает значение атрибута в первое такое поле.
* 1011Во-вторых, поскольку тег xml:",chardata" даже не пропускает это поле через UnmarshalXML интерфейса xml.Unmarshaller, вы не можете просто создать новый тип для Text и реализовать этот интерфейс для него, как отмечено вте же документы.(Обратите внимание, что любой тип, кроме [] байта или строки, вызовет ошибку)
  • Если элемент XML содержит символьные данные, эти данные накапливаются в первом структурном поле с тегом ", chardata».Поле структуры может иметь тип [] байт или строку.Если такого поля нет, символьные данные отбрасываются.

Таким образом, самый простой способ справиться с нежелательными символами - это просто заменить их.

Полный пример кода здесь: https://play.golang.org/p/VSDskgfcLng

var Replacer = strings.NewReplacer("&#xA;","","&#x9;","","\n","","\t","")

func recursiveReplace(n *Node) {
    n.Text = Replacer.Replace(n.Text)
    for i := range n.Children {
        recursiveReplace(&n.Children[i])
    }
}

Теоретически можно реализовать интерфейс xml.Unmarshaller для Node, но тогда вам придется иметь дело не только с ручным синтаксическим анализом XML, но и с тем, чтоэто рекурсивная структура.Проще всего удалить нежелательных персонажей по факту.

...