antchfx / xmlquery

xmlquery is Golang XPath package for XML query.
https://github.com/antchfx/xpath
MIT License
444 stars 89 forks source link

Breaking changes between 1.3.14 and 1.3.15 #102

Closed slaskis closed 1 year ago

slaskis commented 1 year ago

We just tried to upgrade xmlquery from 1.3.14 to 1.3.15.

Seemed like a tiny version bump but we have this test which passes for 1.3.14 but fails for 1.3.15 and I just can't figure out what changed in either xmlquery or xmlpath modules to cause this:


func TestXmlquery(t *testing.T) {
    src := `<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body test="1"><ns2:Fault xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns3="http://www.w3.org/2003/05/soap-envelope"><faultcode>ns2:Client</faultcode><faultstring>This is a client fault</faultstring></ns2:Fault></S:Body></S:Envelope>`
    n1, err := xmlquery.Parse(strings.NewReader(src))
    if err != nil {
        t.Fatal(err)
    }
    n2, err := xmlquery.Query(n1, `//S:Envelope/S:Body/ns2:Fault/faultcode`)
    if err != nil {
        t.Fatal(err)
    }
    if n2 == nil {
        t.Error("unable to query xpath") // this is triggered in 1.3.15
    }
}
slaskis commented 1 year ago

We actually had to revert to 1.3.13 but it might be a different issue in addition to this because this particular test passes in 1.3.14...

zhengchun commented 1 year ago

In version v1.3.14, I committed code to fixing #96, may be will causing this issue.

in your example document, xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" and xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/" have the same NamespaceURL: http://schemas.xmlsoap.org/soap/envelope/.

zhengchun commented 1 year ago

I am fixing, it might take a while.

slaskis commented 1 year ago

in your example document, xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" and xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/" have the same NamespaceURL: http://schemas.xmlsoap.org/soap/envelope/.

yep. it's a very strange SOAP xml we get, unfortunately it's not something we can control as it's a third-party response.

I am fixing, it might take a while.

thank you, I really appreciate the fast response!

zhengchun commented 1 year ago

fixed, you can try get the latest commit: https://github.com/antchfx/xmlquery/commit/0f42df816521e5c68beb49f40fac1d6c194df314

slaskis commented 1 year ago

very nice, that works great for that particular test.

now I got stuck on the next test, which is a little bit more complex but works on 1.3.13:

func TestXmlquery_1_3_16(t *testing.T) {
    src := `<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cai3g="http://schemas.example.com/cai3g1.2/"><S:Header><cai3g:SessionId>abc</cai3g:SessionId></S:Header><S:Body><ns2:Fault xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns3="http://www.w3.org/2003/05/soap-envelope"><faultcode>ns2:Server</faultcode><faultstring>This is a server fault</faultstring><detail><Cai3gFault:Cai3gFault xmlns="http://schemas.example.com/cai3g1.2/" xmlns:Cai3gFault="http://schemas.example.com/cai3g1.2/">
    <faultcode>4006</faultcode>
    <faultreason>
    <reasonText>External error.</reasonText>
    </faultreason>
    <faultrole>MF</faultrole>
    <details>
    <PGFault:PGFault xmlns="http://schemas.example.com/pg/1.0" xmlns:PGFault="http://schemas.example.com/pg/1.0">
    <errorcode>900002</errorcode>
    <errormessage>Could not process request due to resource limitation. Could not process request due to resource limitation. No functional connections for the network element [VM]</errormessage>
    <errordetails>&lt;elementResult>
    &lt;node>VMSV&lt;/node>
    &lt;command>get&lt;/command>
    &lt;nodeResponseCode>1098&lt;/nodeResponseCode>
    &lt;nodeResponseMessage>Could not process request due to resource limitation. Could not process request due to resource limitation. No functional connections for the network element [VM]&lt;/nodeResponseMessage>
    &lt;/elementResult>
    - [Processed by PG Node: aa800eda4.ddc.example.net]</errordetails>
    </PGFault:PGFault>
    </details>
    </Cai3gFault:Cai3gFault></detail></ns2:Fault></S:Body></S:Envelope>`
    n1, err := xmlquery.Parse(strings.NewReader(src))
    if err != nil {
        t.Fatal(err)
    }
    n2, err := xmlquery.Query(n1, `//S:Envelope/S:Body/ns2:Fault/detail/Cai3gFault:Cai3gFault`)
    if err != nil {
        t.Fatal(err)
    }
    if n2 == nil {
        t.Error("unable to query xpath") // fails on xmlquery@1.3.16
    }
}
zhengchun commented 1 year ago

@slaskis, according #96(https://github.com/antchfx/xmlquery/commit/a86901ead4bbfbad5119b5d989656cd3f54773f6#diff-1596bd8ceb74246828aacab827b39a33075c86baa627fbbeb7491bd31eef1169R108), your XML <Cai3gFault:Cai3gFault xmlns="http://schemas.example.com/cai3g1.2/" xmlns:Cai3gFault="http://schemas.example.com/cai3g1.2/" will be consider it's a default NamespaceURL, so Cai3gFault:Cai3gFaults prefix name Cai3gFault will be ignored when parsing XML. When you output the entire document to XML file, it likes the below:

<Cai3gFault xmlns="http://schemas.example.com/cai3g1.2/" xmlns:Cai3gFault="http://schemas.example.com/cai3g1.2/">
...
</Cai3gFault>

There are no good method can sove this issue, because it will conflict with #96, if fix this issue but #96 will still output <svg:svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"></svg:svg>

The temporary method is change your xpath to

n2, err := xmlquery.Query(n1, '//S:Envelope/S:Body/ns2:Fault/detail/Cai3gFault')

or you can try using xpath new feature CompileWithNS(), see #15

expr, _ := xpath.CompileWithNS("//S:Envelope/S:Body/ns2:Fault/detail/Cai3gFault:Cai3gFault", map[string]string{
        "S":   "http://schemas.xmlsoap.org/soap/envelope/",
        "ns2": "http://schemas.xmlsoap.org/soap/envelope/",
        "Cai3gFault":   "http://schemas.example.com/cai3g1.2/",
    })
node := xmlquery.QuerySelector(n1, expr)
zhengchun commented 1 year ago

fixed in https://github.com/antchfx/xmlquery/releases/tag/v1.3.16