在Go语言中解析多个XML标签

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

Parse multiple XML Tags in Go

问题

我正在尝试解析一个包含以下输出的 sslscan 的 xml 文件。我想用 Go 来解析它。

  1. <document title="SSLScan Results">
  2. <ssltest host="x.x.x.x" port="443">
  3. <cipher status="accepted" sslversion="TLSv1.0" bits="256" cipher="DHE-RSA-CAMELLIA256-SHA" dhebits="2048" />
  4. .
  5. .
  6. <cipher status="accepted" sslversion="TLSv1.2" bits="112" cipher="DES-CBC3-SHA" /> .
  7. <certificate>
  8. <not-valid-before>Jun 6 00:00:00 2014 GMT</not-valid-before>
  9. <not-valid-after>Jul 4 23:59:59 2017 GMT</not-valid-after>
  10. </certificate>
  11. </ssltest>
  12. </document>

代码:

  1. type XMLStrap struct {
  2. Status string `xml:"status,attr"`
  3. SSLversion string `xml:"sslversion,attr"`
  4. Bits string `xml:"bits,attr"`
  5. Cipher string `xml:"cipher,attr"`
  6. }
  7. type XMLStraps struct {
  8. XMLName xml.Name `xml:"document"`
  9. Straps []XMLStrap `xml:"ssltest>cipher"`
  10. }
  11. func ReadStraps(reader io.Reader) ([]XMLStrap, error) {
  12. var xmlStraps XMLStraps
  13. if err := xml.NewDecoder(reader).Decode(&xmlStraps); err != nil {
  14. return nil, err
  15. }
  16. return xmlStraps.Straps, nil
  17. }
  18. func main() {
  19. strapsFilePath, err := filepath.Abs("straps.xml")
  20. if err != nil {
  21. fmt.Println(err)
  22. os.Exit(1)
  23. }
  24. file, err := os.Open(strapsFilePath)
  25. if err != nil {
  26. fmt.Println(err)
  27. os.Exit(1)
  28. }
  29. defer file.Close()
  30. xmlStraps, err := ReadStraps(file)
  31. if err != nil {
  32. fmt.Println(err)
  33. os.Exit(1)
  34. }
  35. for i := 0; i < len(xmlStraps); i++ {
  36. fmt.Printf("%s %s %s %s\n", xmlStraps[i].Status, xmlStraps[i].SSLversion, xmlStraps[i].Bits, xmlStraps[i].Cipher)
  37. }
  38. }

一切都正常工作,但我不知道如何解析 <certificate><not-valid-before> 中的日期,而不创建一个新的 reader。我尝试将前两个结构体更改为:

  1. type XMLStrap struct {
  2. Status string `xml:"cipher>status,attr"`
  3. SSLversion string `xml:"cipher>sslversion,attr"`
  4. Bits string `xml:"cipher>bits,attr"`
  5. Cipher string `xml:"cipher>cipher,attr"`
  6. Cert string `xml:"certificate>not-valid-after,chardata"`
  7. }
  8. type XMLStraps struct {
  9. XMLName xml.Name `xml:"document"`
  10. Straps []XMLStrap `xml:"ssltest"`
  11. }

但这样不起作用。

xml: cipher>status chain not valid with attr flag exit status 1

显然,在较旧的 Go 版本中,它是可以工作的。

英文:

I'm trying to parse an xml file for sslscan which has the following output (shortened).
I want to parse it with Go.

  1. &lt;document title=&quot;SSLScan Results&quot;&gt;
  2. &lt;ssltest host=&quot;x.x.x.x&quot; port=&quot;443&quot;&gt;
  3. &lt;cipher status=&quot;accepted&quot; sslversion=&quot;TLSv1.0&quot; bits=&quot;256&quot; cipher=&quot;DHE-RSA-CAMELLIA256-SHA&quot; dhebits=&quot;2048&quot; /&gt;
  4. .
  5. .
  6. &lt;cipher status=&quot;accepted&quot; sslversion=&quot;TLSv1.2&quot; bits=&quot;112&quot; cipher=&quot;DES-CBC3-SHA&quot; /&gt; .
  7. &lt;certificate&gt;
  8. &lt;not-valid-before&gt;Jun 6 00:00:00 2014 GMT&lt;/not-valid-before&gt;
  9. &lt;not-valid-after&gt;Jul 4 23:59:59 2017 GMT&lt;/not-valid-after&gt;
  10. &lt;/certificate&gt;
  11. &lt;/ssltest&gt;
  12. &lt;/document&gt;

Code:

  1. type XMLStrap struct {
  2. Status string `xml:&quot;status,attr&quot;`
  3. SSLversion string `xml:&quot;sslversion,attr&quot;`
  4. Bits string `xml:&quot;bits,attr&quot;`
  5. Cipher string `xml:&quot;cipher,attr&quot;`
  6. }
  7. type XMLStraps struct {
  8. XMLName xml.Name `xml:&quot;document&quot;`
  9. Straps []XMLStrap `xml:&quot;ssltest&gt;cipher&quot;`
  10. }
  11. func ReadStraps(reader io.Reader) ([]XMLStrap, error) {
  12. var xmlStraps XMLStraps
  13. if err := xml.NewDecoder(reader).Decode(&amp;xmlStraps); err != nil {
  14. return nil, err
  15. }
  16. return xmlStraps.Straps, nil
  17. }
  18. func main() {
  19. strapsFilePath, err := filepath.Abs(&quot;straps.xml&quot;)
  20. if err != nil {
  21. fmt.Println(err)
  22. os.Exit(1)
  23. }
  24. file, err := os.Open(strapsFilePath)
  25. if err != nil {
  26. fmt.Println(err)
  27. os.Exit(1)
  28. }
  29. defer file.Close()
  30. xmlStraps, err := ReadStraps(file)
  31. if err != nil {
  32. fmt.Println(err)
  33. os.Exit(1)
  34. }
  35. for i := 0; i &lt; len(xmlStraps); i++ {
  36. fmt.Printf(&quot;%s %s %s %s\n&quot;, xmlStraps[i].Status, xmlStraps[i].SSLversion, xmlStraps[i].Bits, xmlStraps[i].Cipher)
  37. }
  38. }

Everything works fine but I have no idea how to parse the date in &lt;certificate&gt;&lt;not-valid-before&gt; without creating a new reader?

I tried to change the first two structs to

  1. type XMLStrap struct {
  2. Status string `xml:&quot;cipher&gt;status,attr&quot;`
  3. SSLversion string `xml:&quot;cipher&gt;sslversion,attr&quot;`
  4. Bits string `xml:&quot;cipher&gt;bits,attr&quot;`
  5. Cipher string `xml:&quot;cipher&gt;cipher,attr&quot;`
  6. Cert string `xml:&quot;certificate&gt;not-valid-after,chardata&quot;`
  7. }
  8. type XMLStraps struct {
  9. XMLName xml.Name `xml:&quot;document&quot;`
  10. Straps []XMLStrap `xml:&quot;ssltest&quot;`
  11. }

but this doesn't work.

xml: cipher&gt;status chain not valid with attr flag
exit status 1

Apparently in older versions of Go it worked.

答案1

得分: 0

我不是代码翻译器,但我可以帮你理解这段代码的含义。这段代码定义了一些结构体类型,并实现了一个函数。下面是代码的翻译:

  1. type XMLStrap struct {
  2. Status string `xml:"status,attr"`
  3. SSLversion string `xml:"sslversion,attr"`
  4. Bits string `xml:"bits,attr"`
  5. Cipher string `xml:"cipher,attr"`
  6. Valid string ""
  7. }
  8. type Certs struct {
  9. Cert string `xml:"not-valid-after"`
  10. }
  11. type XMLStraps struct {
  12. XMLName xml.Name `xml:"document"`
  13. Straps []XMLStrap `xml:"ssltest>cipher"`
  14. Validation Certs `xml:"ssltest>certificate"`
  15. }
  16. func ReadStraps(reader io.Reader) ([]XMLStrap, error) {
  17. var xmlStraps XMLStraps
  18. if err := xml.NewDecoder(reader).Decode(&xmlStraps); err != nil {
  19. return nil, err
  20. }
  21. xmlStraps.Straps[0].Valid = xmlStraps.Validation.Cert
  22. return xmlStraps.Straps, nil
  23. }

这段代码定义了三个结构体类型:XMLStrapCertsXMLStrapsXMLStrap结构体有五个字段,分别是StatusSSLversionBitsCipherValidCerts结构体只有一个字段CertXMLStraps结构体包含了一个XMLName字段和两个嵌套的结构体字段StrapsValidation

ReadStraps函数接收一个io.Reader类型的参数,并返回一个[]XMLStrap类型的切片和一个错误。函数内部首先创建了一个XMLStraps类型的变量xmlStraps,然后使用xml.NewDecoder(reader).Decode(&xmlStraps)将输入的XML数据解码到xmlStraps变量中。最后,将xmlStraps.Validation.Cert赋值给xmlStraps.Straps[0].Valid,并返回xmlStraps.Straps切片和一个可能发生的错误。

希望这能帮到你!如果你有任何其他问题,请随时问我。

英文:

I had to allocate the parameter of a new object to the object which was returned. I tried this before but I did a mistake

  1. type XMLStrap struct {
  2. Status string `xml:&quot;status,attr&quot;`
  3. SSLversion string `xml:&quot;sslversion,attr&quot;`
  4. Bits string `xml:&quot;bits,attr&quot;`
  5. Cipher string `xml:&quot;cipher,attr&quot;`
  6. Valid string &quot;&quot;
  7. }
  8. type Certs struct {
  9. Cert string `xml:&quot;not-valid-after&quot;`
  10. }
  11. type XMLStraps struct {
  12. XMLName xml.Name `xml:&quot;document&quot;`
  13. Straps []XMLStrap `xml:&quot;ssltest&gt;cipher&quot;`
  14. Validation Certs `xml:&quot;ssltest&gt;certificate&quot;`
  15. }
  16. func ReadStraps(reader io.Reader) ([]XMLStrap, error) {
  17. var xmlStraps XMLStraps
  18. if err := xml.NewDecoder(reader).Decode(&amp;xmlStraps); err != nil {
  19. return nil, err
  20. }
  21. xmlStraps.Straps[0].Valid = xmlStraps.Validation.Cert
  22. return xmlStraps.Straps, nil
  23. }

huangapple
  • 本文由 发表于 2015年10月20日 15:49:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/33230936.html
匿名

发表评论

匿名网友

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

确定