2016-10-17 2 views
2

У меня возникла проблема с распараллеливанием XML с символами Unicode.golang XML закончил синтаксический разбор с ошибкой «недопустимый UTF-8»

При попытке проанализировать XML со стандартными английскими символами, он обрабатывает весь файл и отменяет корректность без каких-либо проблем. Однако, если XML-файл содержит символ, например ñ, á или - (em-dash), он перестает анализировать XML и возвращает только элементы в массиве до элемента с этим символом.

Например, вот XML:

<items> 
    <item> 
    <ID value="1" name="Item 1" GCName="Item 1" /> 
    </item> 
    <item> 
    <ID value="2" name="Item 2" GCName="Item 2" /> 
    </item> 
    <item> 
    <ID value="3" name="Item 3" GCName="Item 3 With ñ" /> 
    </item> 
    <item> 
    <ID value="4" name="Item 4" GCName="Item 4" /> 
    </item> 
</items> 

Это мой Go код (грубая без импорта):

# main.go 

type Response struct { 
    Items []Items `xml:"items"` 
} 

type Items struct { 
    Item []Item `xml:"item"` 
} 

type Item struct { 
    ID ItemID `xml:"ID"` 
} 

type ItemID struct { 
    Value string `xml:"value,attr"` 
    Name string `xml:"name,attr"` 
    GCName string `xml:"GCName,attr"` 
} 

func main() { 
    xmlFile, err := os.Open("C:\path\to\xml\file.xml") 
    if err != nil { 
     fmt.Println("Error opening file!") 
     fmt.Println(err.Error()) 
    } 
    defer xmlFile.Close() 

    xmlData, err := io.ReadAll(xmlFile) 
    if err != nil { 
     fmt.Println("Error reading file!") 
     fmt.Println(err.Error()) 
    } 

    var response Response 
    err := xml.Unmarshal(xmlData, &response) 
    if err != nil { 
     fmt.Println("Error unmarshaling XML") 
     fmt.Println(err.Error()) 
    } 
    fmt.Println(response) 
} 

Этот код выведет только первые два пункта, как будто они были единственными. Он также выдает:

Error unmarshaling XML 
XML syntax error on line 9; Invalid UTF-8 

Я также попытался использовать xml.Decoder с CharsetReader, используя другую кодировку, но это не дало разные результаты. FWIW, Я использую Windows.

Есть ли способ обойти эту ошибку? Поменяйте «плохие» символы на что-то еще? Насколько я понял, эти персонажи являются действительными UTF-8 ... так что дает ???

Заранее благодарен!

+1

вы можете попробовать [фильтр недействительных UTF-8 символов] (https://github.com/kisielk/gorge /blob/master/util/util.go) –

+0

О, черт возьми, это исправило это. Это какая-то магия. Можете ли вы опубликовать ответ, чтобы я мог принять его? –

+0

У вас было несколько опечаток там и структуры, которые там не нужны, но в ОС он скомпилирован и работает без проблем. Странно, я думал, что это везде одинаково. - https://play.golang.org/p/l5tijHxoZV 'go version go1.6 darwin/amd64' – s7anley

ответ

3

Читатель, который отфильтровывает недействительные UTF-8 символов

package main 

    import (
    "bufio" 
    "io" 
    "unicode" 
    "unicode/utf8" 
    ) 

    // ValidUTF8Reader implements a Reader which reads only bytes that constitute valid UTF-8 
    type ValidUTF8Reader struct { 
     buffer *bufio.Reader 
    } 

    // Function Read reads bytes in the byte array b. n is the number of bytes read. 
    func (rd ValidUTF8Reader) Read(b []byte) (n int, err error) { 
     for { 
      var r rune 
      var size int 
      r, size, err = rd.buffer.ReadRune() 
      if err != nil { 
       return 
      } 
      if r == unicode.ReplacementChar && size == 1 { 
       continue 
      } else if n+size < len(b) { 
       utf8.EncodeRune(b[n:], r) 
       n += size 
      } else { 
       rd.buffer.UnreadRune() 
       break 
      } 
     } 
     return 
    } 

    // NewValidUTF8Reader constructs a new ValidUTF8Reader that wraps an existing io.Reader 
    func NewValidUTF8Reader(rd io.Reader) ValidUTF8Reader { 
     return ValidUTF8Reader{bufio.NewReader(rd)} 
    } 

взяты из here

Смежные вопросы