XPathUtil { public static StepList steps(final AttributeDescriptor root, final String xpathExpression, final NamespaceSupport namespaces) throws IllegalArgumentException { if (root == null) { throw new NullPointerException("root"); } if (xpathExpression == null) { throw new NullPointerException("xpathExpression"); } String expression = xpathExpression.trim(); if ("".equals(expression)) { throw new IllegalArgumentException("expression is empty"); } StepList steps = new StepList(); if ("/".equals(expression)) { expression = root.getName().getLocalPart(); } if (expression.startsWith("/")) { expression = expression.substring(1); } final List<String> partialSteps = splitPath(expression); if (partialSteps.size() == 0) { throw new IllegalArgumentException("no steps provided"); } int startIndex = 0; for (int i = startIndex; i < partialSteps.size(); i++) { String step = partialSteps.get(i); if ("..".equals(step)) { steps.remove(steps.size() - 1); } else if (".".equals(step)) { continue; } else { int index = 1; boolean isXmlAttribute = false; boolean isIndexed = false; String predicate = null; String stepName = step; if (step.indexOf('[') != -1) { int start = step.indexOf('['); int end = step.indexOf(']'); stepName = step.substring(0, start); String s = step.substring(start + 1, end); Scanner scanner = new Scanner(s); if (scanner.hasNextInt()) { index = scanner.nextInt(); isIndexed = true; } else { predicate = s; } } if (step.charAt(0) == '@') { isXmlAttribute = true; stepName = stepName.substring(1); } QName qName = deglose(stepName, root, namespaces, isXmlAttribute); if (predicate == null) { steps.add(new Step(qName, index, isXmlAttribute, isIndexed)); } else { steps.add(new Step(qName, isXmlAttribute, predicate)); } } } if (root != null && steps.size() > 1) { Step step = (Step) steps.get(0); Name rootName = root.getName(); QName stepName = step.getName(); if (Types.equals(rootName, stepName)) { LOGGER.fine("removing root name from xpath " + steps + " as it is redundant"); steps.remove(0); } } return steps; }  static StepList rootElementSteps(final AttributeDescriptor rootElement,
            final NamespaceSupport namespaces); static StepList steps(final AttributeDescriptor root, final String xpathExpression,
            final NamespaceSupport namespaces); static boolean equals(Name targetNodeName, StepList targetXPath);  }
@Test public void testSteps() throws Exception { FeatureType complexType = ComplexTestData .createExample01MultiValuedComplexProperty(new UniqueNameFeatureTypeFactoryImpl()); Name name = complexType.getName(); AttributeDescriptor descriptor = new AttributeDescriptorImpl(complexType, name, 0, Integer.MAX_VALUE, true, null); NamespaceSupport namespaces = new NamespaceSupport(); namespaces.declarePrefix("wq", name.getNamespaceURI()); try { XPathUtil.steps(descriptor, null, namespaces); fail("passed null"); } catch (NullPointerException e) { } List expected; String xpath; xpath = "/"; assertEquals(1, XPathUtil.steps(descriptor, xpath, namespaces).size()); XPathUtil.Step step = (XPathUtil.Step) XPathUtil.steps(descriptor, xpath, namespaces).get(0); QName rootQName = new QName(name.getNamespaceURI(), name.getLocalPart()); assertEquals(rootQName, step.getName()); expected = Collections.singletonList(new XPathUtil.Step(rootQName, 1)); xpath = "wq_plus"; assertEquals(expected, XPathUtil.steps(descriptor, xpath, namespaces)); expected = Collections.singletonList(new XPathUtil.Step(rootQName, 1)); xpath = "/wq_plus"; assertEquals(expected, XPathUtil.steps(descriptor, xpath, namespaces)); expected = Collections.singletonList(new XPathUtil.Step(rootQName, 1)); xpath = "wq_plus/measurement/result/../../measurement/determinand_description/../.."; assertEquals(expected, XPathUtil.steps(descriptor, xpath, namespaces)); expected = Arrays.asList(new XPathUtil.Step[] { new XPathUtil.Step(new QName(rootQName.getNamespaceURI(), "measurement"), 2), new XPathUtil.Step(new QName(rootQName.getNamespaceURI(), "result"), 1) }); xpath = "wq_plus/measurement/result/../../measurement[2]/result"; assertEquals(expected, XPathUtil.steps(descriptor, xpath, namespaces)); expected = Arrays.asList(new XPathUtil.Step[] { new XPathUtil.Step(new QName(rootQName.getNamespaceURI(), "measurement"), 1), new XPathUtil.Step(new QName(rootQName.getNamespaceURI(), "result"), 1) }); xpath = "wq_plus/measurement/result/../result/."; assertEquals(expected, XPathUtil.steps(descriptor, xpath, namespaces)); expected = Arrays.asList(new XPathUtil.Step[] { new XPathUtil.Step(new QName(rootQName .getNamespaceURI(), "measurement"), 5) }); xpath = "measurement/result/../../measurement[5]"; assertEquals(expected, XPathUtil.steps(descriptor, xpath, namespaces)); }
@Test public void testStepsWithXmlAttribute() throws Exception { FeatureType complexType = ComplexTestData .createExample01MultiValuedComplexProperty(new UniqueNameFeatureTypeFactoryImpl()); Name name = complexType.getName(); AttributeDescriptor descriptor = new AttributeDescriptorImpl(complexType, name, 0, Integer.MAX_VALUE, true, null); QName rootQName = new QName(name.getNamespaceURI(), name.getLocalPart()); NamespaceSupport namespaces = new NamespaceSupport(); namespaces.declarePrefix("wq", name.getNamespaceURI()); namespaces.declarePrefix("xlink", XLINK.NAMESPACE); StepList steps = XPathUtil.steps(descriptor, "wq_plus/measurement[2]/@xlink:href", namespaces); assertNotNull(steps); assertEquals(steps.toString(), 2, steps.size()); XPathUtil.Step step1 = new XPathUtil.Step(new QName(rootQName.getNamespaceURI(), "measurement"), 2, false); XPathUtil.Step step2 = new XPathUtil.Step(XLINK.HREF, 1, true); assertEquals(step1, steps.get(0)); assertEquals(step2, steps.get(1)); }