XPathParser { protected AxisStep parseAxisStep( TokenStream tokens ) { NodeTest nodeTest = null; if (tokens.canConsume('@')) { nodeTest = new AttributeNameTest(parseNameTest(tokens)); } else if (tokens.matches('*')) { nodeTest = parseNodeTest(tokens); } else if (tokens.matches("child", ":", ":") || tokens.matches("attribute", ":", ":") || tokens.matches("self", ":", ":") || tokens.matches("descendant", ":", ":") || tokens.matches("descendant-or-self", ":", ":") || tokens.matches("following-sibling", ":", ":") || tokens.matches("following", ":", ":") || tokens.matches("namespace", ":", ":")) { throw new ParsingException( tokens.nextPosition(), "XPath non-abbreviated forward steps (e.g., 'child::', 'attribute::', 'self::', 'descendant::', 'descendant-or-self::', 'following-sibling::', 'following::', or 'namespace::') are not supported"); } else if (tokens.matches("..")) { throw new ParsingException(tokens.nextPosition(), "XPath abbreviated reverse steps (e.g., '..') are not supported"); } else if (tokens.matches("parent", ":", ":") || tokens.matches("ancestor-or-self", ":", ":") || tokens.matches("preceding-sibling", ":", ":") || tokens.matches("preceding", ":", ":") || tokens.matches("ancestor", ":", ":")) { throw new ParsingException( tokens.nextPosition(), "XPath non-abbreviated reverse steps (e.g., 'parent::', 'ancestor::', 'ancestor-or-self::', 'preceding-or-sibling::', or 'preceding::') are not supported"); } else if (tokens.matches(ANY_VALUE, ":", ANY_VALUE) && tokens.matches(XPathTokenizer.NAME, XPathTokenizer.SYMBOL, XPathTokenizer.NAME)) { nodeTest = parseQName(tokens); } else if (tokens.matches(XPathTokenizer.NAME)) { nodeTest = parseNodeTest(tokens); } else { return null; } List<Component> predicates = parsePredicates(tokens); return new AxisStep(nodeTest, predicates); } XPathParser( TypeSystem context ); Component parseXPath( String xpath );  }
@Test public void shouldParseAxisStepFromAttributeWithNoPrefix() { assertThat(parser.parseAxisStep(tokenize("@foo")), is(axisStep(attributeNameTest(nameTest("foo"))))); }
@Test public void shouldParseAxisStepFromAttributeWithPrefix() { assertThat(parser.parseAxisStep(tokenize("@foo:bar")), is(axisStep(attributeNameTest(nameTest("foo", "bar"))))); }
@Test( expected = ParsingException.class ) public void shouldFailToParseAxisStepFromInvalidAttributeName() { parser.parseAxisStep(tokenize("@3:invalidName")); }
@Test public void shouldParseAxisStepFromNameWithNoPrefix() { assertThat(parser.parseAxisStep(tokenize("foo")), is(axisStep(nameTest("foo")))); }
@Test public void shouldParseAxisStepFromNameWithPrefix() { assertThat(parser.parseAxisStep(tokenize("foo:bar")), is(axisStep(nameTest("foo", "bar")))); }
@Test public void shouldReturnNullFromParseAxisStepIfInvalidName() { assertThat(parser.parseAxisStep(tokenize("3:invalidName")), is(nullValue())); }
@Test public void shouldParseAxisStepFromWildcard() { assertThat(parser.parseAxisStep(tokenize("*")), is(axisStep(wildcard()))); }
@Test public void shouldParseAxisStepFromWildcardPrefixAndNonWildcardLocalName() { assertThat(parser.parseAxisStep(tokenize("*:foo")), is(axisStep(nameTest(null, "foo")))); }
@Test public void shouldParseAxisStepFromWithPrefixAndWildcardLocalName() { assertThat(parser.parseAxisStep(tokenize("foo:*")), is(axisStep(nameTest("foo", null)))); }
@Test public void shouldParseAxisStepFromWildcardPrefixAndNonWildcardLocalNameWithPredicates() { assertThat(parser.parseAxisStep(tokenize("*:name[3]")), is(axisStep(nameTest(null, "name"), literal("3")))); }
@Test public void shouldParseAxisStepFromWildcardLocalNameWithPredicates() { assertThat(parser.parseAxisStep(tokenize("*[3]")), is(axisStep(wildcard(), literal("3")))); }
@Test public void shouldParseAxisStepFromWildcardPrefixAndLocalNameWithPredicates() { assertThat(parser.parseAxisStep(tokenize("*:*[3]")), is(axisStep(wildcard(), literal("3")))); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedSelfAxis() { parser.parseAxisStep(tokenize("self::x")); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedChildAxis() { parser.parseAxisStep(tokenize("child::x")); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedDescendantAxis() { parser.parseAxisStep(tokenize("descendant::x")); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedDescendantOrSelfAxis() { parser.parseAxisStep(tokenize("descendant-or-self::x")); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedFollowingAxis() { parser.parseAxisStep(tokenize("following::x")); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedFollowingSiblingAxis() { parser.parseAxisStep(tokenize("following-sibling::x")); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedNamespaceAxis() { parser.parseAxisStep(tokenize("namespace::x")); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedParentAxis() { parser.parseAxisStep(tokenize("parent::x")); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedAncestorAxis() { parser.parseAxisStep(tokenize("ancestor::x")); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedAncestorOrSelfAxis() { parser.parseAxisStep(tokenize("ancestor-or-self::x")); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedPrecedingAxis() { parser.parseAxisStep(tokenize("preceding::x")); }
@Test( expected = ParsingException.class ) public void shouldFailToParseNonAbbreviatedPrecedingSiblingAxis() { parser.parseAxisStep(tokenize("preceding-sibling::x")); }