Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Only namespace prefixes bound on the root node are considered by document.xpath(_ xpath: String) #60

Open
1 task done
martin-cowie opened this issue Jun 29, 2017 · 3 comments

Comments

@martin-cowie
Copy link

Description:

  • Expected behaviour:

XML namespaces can be bound to a prefix at any element in a document. They can be bound within an element that uses that namespace prefix. XPath expressions should be able to use the same prefixes. E.g given the document:

<root>
    <u:BrowseResponse xmlns:u="urn:foo.bar" />
</root>

the XPath expression /root/u:BrowseResponse should resolve to a nodelist of 1 element.

  • Actual behaviour:

The XPath expression /root/u:BrowseResponse resolve to a nodelist of 0 elements and the following is printed

XPath error : Undefined namespace prefix
XPath error : Invalid expression

If the document is amended such that the prefix u: is bound at the root element the xpath expression evaluates correctly.

Environment

  • Package Manager:
    • CocoaPods, version: 1.2.2
  • Fuzi version: 1.0.1
  • Xcode version: 8.3.3

How to reproduce:

The following test fails, demonstrating the issue.

    func testNestedNamespacePrefixWithXPath() {
        let docStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root><u:BrowseResponse xmlns:u=\"urn:foo.bar\"/></root>"

        do {
            let document = try Fuzi.XMLDocument(string: docStr)
            let nodes = document.xpath("/root/u:BrowseResponse")
            XCTAssertFalse(nodes.isEmpty)
        } catch let error {
            print(error)
            XCTFail(String(describing:error))
        }
    }
@cezheng
Copy link
Owner

cezheng commented Jun 29, 2017

Seems like a duplicate of #25
This is how libxml2 deals with namespaces, you have to define a prefix yourself before using it with XPath queries

@martin-cowie
Copy link
Author

martin-cowie commented Jun 30, 2017

Thanks for coming back to me Cezheng.

I use Document.definePrefix(_ prefix: String, defaultNamespace ns: String) elsewhere in my code to handle a default namespace. Alas, using the same technique here doesn't work, possibly because urn:foo.bar is not bound as a default namespace in the XML:

    func testNestedNamespacePrefixWithXPath() {
        let docStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root><u:BrowseResponse xmlns:u=\"urn:foo.bar\"/></root>"
        do {
            let document = try Fuzi.XMLDocument(string: docStr)
            document.definePrefix("u", defaultNamespace: "urn:foo.bar") // New code
            let nodes = document.xpath("/root/u:BrowseResponse")
            XCTAssertFalse(nodes.isEmpty)
        } catch let error {
            print(error)
            XCTFail(String(describing:error))
        }
    }

@cezheng
Copy link
Owner

cezheng commented Jul 2, 2017

the relevant code is here

Seems if the namespace definition is under root element, the query should work. And it doesn't make sense to traverse the whole doc just looking for namespaces.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants