Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

XPath is not working correctly on XML documents with schemas #143

Open
skapral opened this issue Feb 11, 2018 · 4 comments
Open

XPath is not working correctly on XML documents with schemas #143

skapral opened this issue Feb 11, 2018 · 4 comments

Comments

@skapral
Copy link
Contributor

skapral commented Feb 11, 2018

Assume the following test suite:

public class ProbaTest {
    @Test
    public void test() throws Exception {
        new XMLDocument(
                ProbaTest.class.getClassLoader().getResourceAsStream("pom.xml")
        ).xpath("//project/scm/url/text()").get(0);
    }

    @Test
    public void test2() throws Exception {
        new StrictXML(
                new XMLDocument(
                        ProbaTest.class.getClassLoader().getResourceAsStream("pom.xml")
                )
        ).xpath("//project/scm/url/text()").get(0);
    }

    @Test
    public void test3() throws Exception {
        new XMLDocument(
                ProbaTest.class.getClassLoader().getResourceAsStream("pom_wo_schemas.xml")
        ).xpath("//project/scm/url/text()").get(0);
    }
}

...where pom.xml is the POM file, taken from Takes framework (link) and pom_wo_schemas.xml is the same POM file with all attributes from root project element removed.

First two tests fail with similar exception:

com.jcabi.xml.ListWrapper$NodeNotFoundException: XPath '//project/scm/url/text()' not found in '<?xml version="1.0" encoding="UTF-8" standalone="n..13243../profile>\uA  </profiles>\uA</project>\uA': Index (0) is out of bounds (size=0)
	at com.jcabi.xml.ListWrapper.get(ListWrapper.java:162)
	at proba.ProbaTest.test2(ProbaTest.java:21)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
	at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
	at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
	at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
	at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
	at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)

Third successfully passes.

It seems that either jcabi xml is not workable on XML documents with schemas referenced in root node, or it misses the necessary documentation.

Complete test suite can be found here

@0crat
Copy link

0crat commented Feb 11, 2018

@yegor256/z please, pay attention to this issue

@yegor256
Copy link
Member

@skapral here is what you need:

new XMLDocument(ProbaTest.class.getClassLoader().getResourceAsStream("pom.xml"))
  .registerNs("m", "http://maven.apache.org/POM/4.0.0")
  .xpath("//m:project/m:scm/m:url/text()")
  .get(0);

@borizm
Copy link

borizm commented Mar 18, 2018

XMLDocument should have the initialization of the factory delayed and all the constructors should be private or protected, and the builder pattern should be used.
This is dictated by the need of delaying of the setting:
documentFactory.setNamespaceAware(namespaceAwareness);
to true, base on the fact registerNs() was invoked or not.

It could look like that:

XMLDocument.of()
  .namespaces().put("m", "http://maven.apache.org/POM/4.0.0")
  .from(ProbaTest.class.getClassLoader().getResourceAsStream("pom.xml"))
  .build()
  .xpath("//m:project/m:scm/m:url/text()")
  .get(0);

or (without namespaces):

XMLDocument.of()
  .from(ProbaTest.class.getClassLoader().getResourceAsStream("pom.xml"))
  .build()
  .xpath("//project/scm/url/text()")
  .get(0);

Of course it will break the "contract" with all the existing code that uses this class.

@longtimeago
Copy link

documentFactory.setNamespaceAware(namespaceAwareness);

@borizm is this what actually prevents using proper search through XMLs with default namespace?

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

No branches or pull requests

5 participants