英文:
Custom xml decoder issue
问题
我有多个测试用例通过了,但是这个测试用例失败了。我在这里漏掉了什么导致解码器错误地读取了目标键的内容?
const respGenericFault1 = `<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/1999/XMLSchema">
   <SOAP-ENV:Body>
     <SOAP-ENV:Fault>
         <faultcode xsi:type="xsd:string">SOAP-ENV:Client</faultcode>
         <faultstring xsi:type="xsd:string">Failed to validate</faultstring>
     </SOAP-ENV:Fault>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>`
type Fault struct {
	FaultCode, FaultString string
}
func (f Fault) Error() string {
	return "Fault Code: '" + f.FaultCode + "' FaultString: '" + f.FaultString + "'"
}
func ParseFault(b []byte) error {
	reader := bytes.NewReader(b)
	d := xml.NewDecoder(reader)
	var start xml.StartElement
	fault := Fault{}
	found := false
	// iterate through the tokens
	for {
		tok, _ := d.Token()
		if tok == nil {
			break
		}
		// switch on token type
		switch t := tok.(type) {
		case xml.StartElement:
			start = t.Copy()
			fmt.Println(start.Name.Local)
		case xml.CharData:
			key := strings.ToLower(start.Name.Local)
			// fault was found, capture the values and mark as found
			if key == "faultcode" {
				found = true
				fault.FaultCode = string(t)
				fmt.Printf("%#v\n", string(t))
			} else if key == "faultstring" {
				found = true
				fault.FaultString = string(t)
			}
		}
	}
	if found {
		return fault
	}
	return nil
}
func main() {
	err := ParseFault([]byte(respGenericFault1))
	fmt.Printf("%#v\n", err)
}
这是Playground的URL:http://play.golang.org/p/7PFPNsmast
英文:
I have multiple test cases which pass, however this one fails. What am I missing here that is causing the decoder read the content of my target keys incorrectly?
const respGenericFault1 = `<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode xsi:type="xsd:string">SOAP-ENV:Client</faultcode>
<faultstring xsi:type="xsd:string">Failed to validate</faultstring>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>`
type Fault struct {
FaultCode, FaultString string
}
func (f Fault) Error() string {
return "Fault Code: '" + f.FaultCode + "' FaultString: '" + f.FaultString + "'"
}
func ParseFault(b []byte) error {
reader := bytes.NewReader(b)
d := xml.NewDecoder(reader)
var start xml.StartElement
fault := Fault{}
found := false
// iterate through the tokens
for {
tok, _ := d.Token()
if tok == nil {
break
}
// switch on token type
switch t := tok.(type) {
case xml.StartElement:
start = t.Copy()
fmt.Println(start.Name.Local)
case xml.CharData:
key := strings.ToLower(start.Name.Local)
// fault was found, capture the values and mark as found
if key == "faultcode" {
found = true
fault.FaultCode = string(t)
fmt.Printf("%#v\n", string(t))
} else if key == "faultstring" {
found = true
fault.FaultString = string(t)
}
}
}
if found {
return fault
}
return nil
}
func main() {
err := ParseFault([]byte(respGenericFault1))
fmt.Printf("%#v\n", err)
}
Here is the playground url: http://play.golang.org/p/7PFPNsmast
答案1
得分: 2
你的代码成功捕获了faultstring和faultcode,但是接着无意中用包含标签之间空白的xml.CharData覆盖了它们。
这里是修复后的版本:http://play.golang.org/p/s1aFFYtwcX。注释掉第52行可以看到故障模式。
另外,你可以使用encoding/xml Unmarshal将XML直接解析为结构体。参考:http://play.golang.org/p/lOsZRUJ63B
英文:
Your code successfully captures the faultstring and faultcode, but then unintentionally overwrites it with xml.CharData containing the whitespace between tags.
Here is a fixed version: http://play.golang.org/p/s1aFFYtwcX . Comment out line 52 to see the failure mode.
Alternatively, you can use encoding/xml Unmarshal to parse the XML directly into a struct.  See http://play.golang.org/p/lOsZRUJ63B
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论