Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.hamcrest.xml.HasXPath Maven / Gradle / Ivy
package org.hamcrest.xml;
import org.hamcrest.Condition;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.hamcrest.core.IsAnything;
import org.w3c.dom.Node;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.xpath.*;
import static javax.xml.xpath.XPathConstants.STRING;
import static org.hamcrest.Condition.matched;
import static org.hamcrest.Condition.notMatched;
/**
* Applies a Matcher to a given XML Node in an existing XML Node tree, specified by an XPath expression.
*
* @author Joe Walnes
* @author Steve Freeman
*/
public class HasXPath extends TypeSafeDiagnosingMatcher {
public static final NamespaceContext NO_NAMESPACE_CONTEXT = null;
private static final IsAnything WITH_ANY_CONTENT = new IsAnything<>("");
private static final Condition.Step NODE_EXISTS = nodeExists();
private final Matcher valueMatcher;
private final XPathExpression compiledXPath;
private final String xpathString;
private final QName evaluationMode;
/**
* @param xPathExpression XPath expression.
* @param valueMatcher Matcher to use at given XPath.
* May be null to specify that the XPath must exist but the value is irrelevant.
*/
public HasXPath(String xPathExpression, Matcher valueMatcher) {
this(xPathExpression, NO_NAMESPACE_CONTEXT, valueMatcher);
}
/**
* @param xPathExpression XPath expression.
* @param namespaceContext Resolves XML namespace prefixes in the XPath expression
* @param valueMatcher Matcher to use at given XPath.
* May be null to specify that the XPath must exist but the value is irrelevant.
*/
public HasXPath(String xPathExpression, NamespaceContext namespaceContext, Matcher valueMatcher) {
this(xPathExpression, namespaceContext, valueMatcher, STRING);
}
private HasXPath(String xPathExpression, NamespaceContext namespaceContext, Matcher valueMatcher, QName mode) {
this.compiledXPath = compiledXPath(xPathExpression, namespaceContext);
this.xpathString = xPathExpression;
this.valueMatcher = valueMatcher;
this.evaluationMode = mode;
}
@Override
public boolean matchesSafely(Node item, Description mismatch) {
return evaluated(item, mismatch)
.and(NODE_EXISTS)
.matching(valueMatcher);
}
@Override
public void describeTo(Description description) {
description.appendText("an XML document with XPath ").appendText(xpathString);
if (valueMatcher != null) {
description.appendText(" ").appendDescriptionOf(valueMatcher);
}
}
private Condition evaluated(Node item, Description mismatch) {
try {
return matched(compiledXPath.evaluate(item, evaluationMode), mismatch);
} catch (XPathExpressionException e) {
mismatch.appendText(e.getMessage());
}
return notMatched();
}
private static Condition.Step nodeExists() {
return new Condition.Step() {
@Override
public Condition apply(Object value, Description mismatch) {
if (value == null) {
mismatch.appendText("xpath returned no results.");
return notMatched();
}
return matched(String.valueOf(value), mismatch);
}
};
}
private static XPathExpression compiledXPath(String xPathExpression, NamespaceContext namespaceContext) {
try {
final XPath xPath = XPathFactory.newInstance().newXPath();
if (namespaceContext != null) {
xPath.setNamespaceContext(namespaceContext);
}
return xPath.compile(xPathExpression);
} catch (XPathExpressionException e) {
throw new IllegalArgumentException("Invalid XPath : " + xPathExpression, e);
}
}
/**
* Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node has a value at the
* specified xPath
that satisfies the specified valueMatcher
.
* For example:
* assertThat(xml, hasXPath("/root/something[2]/cheese", equalTo("Cheddar")))
*
* @param xPath
* the target xpath
* @param valueMatcher
* matcher for the value at the specified xpath
* @return The matcher.
*/
public static Matcher hasXPath(String xPath, Matcher valueMatcher) {
return hasXPath(xPath, NO_NAMESPACE_CONTEXT, valueMatcher);
}
/**
* Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node has a value at the
* specified xPath
, within the specified namespaceContext
, that satisfies
* the specified valueMatcher
.
* For example:
* assertThat(xml, hasXPath("/root/something[2]/cheese", myNs, equalTo("Cheddar")))
*
* @param xPath
* the target xpath
* @param namespaceContext
* the namespace for matching nodes
* @param valueMatcher
* matcher for the value at the specified xpath
* @return The matcher.
*/
public static Matcher hasXPath(String xPath, NamespaceContext namespaceContext, Matcher valueMatcher) {
return new HasXPath(xPath, namespaceContext, valueMatcher, STRING);
}
/**
* Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node contains a node
* at the specified xPath
, with any content.
* For example:
* assertThat(xml, hasXPath("/root/something[2]/cheese"))
*
* @param xPath
* the target xpath
* @return The matcher.
*/
public static Matcher hasXPath(String xPath) {
return hasXPath(xPath, NO_NAMESPACE_CONTEXT);
}
/**
* Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node contains a node
* at the specified xPath
within the specified namespace context, with any content.
* For example:
* assertThat(xml, hasXPath("/root/something[2]/cheese", myNs))
*
* @param xPath
* the target xpath
* @param namespaceContext
* the namespace for matching nodes
* @return The matcher.
*/
public static Matcher hasXPath(String xPath, NamespaceContext namespaceContext) {
return new HasXPath(xPath, namespaceContext, WITH_ANY_CONTENT, XPathConstants.NODE);
}
}