package ca.umontreal.iro.rali; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.xml.xpath.XPathFactoryConfigurationException; /** * Separates an XPath expression in many different parts * each part is compiled separately */ /** * @author glapalme * */ public class XPathParts { /** * All separate compiled XPath expression parts */ private List parts; /** * Constructor calling @compile to create the list of XPath expression parts * @param patString * @param context */ XPathParts(String patString,NamespaceContext context){ parts=compile(patString,context); } /** * create as many parts as there are node tests * only used in the constructor * * @param patString * @param context * @return */ private List compile(String patString,NamespaceContext context){ XPathTokenizer pt = new XPathTokenizer(patString); List pathParts = new ArrayList(); try{ String tok=pt.nextToken(); StringBuilder sb=new StringBuilder(); while(pt.hasNext()){ if(!tok.equals("/")){ System.err.println("error in:"+patString); System.err.println("path parts should start with / "+tok+" encountered"); System.exit(1); } tok=pt.nextToken(); if(tok.startsWith("@")||(tok.startsWith("attribute::"))){ // an attribute is encountered, gobble rest of expression in a single xp expression sb.append(tok); tok=pt.nextToken(); while(pt.hasNext()){ sb.append(pt.isString()?("\""+tok+"\""):tok); tok=pt.nextToken(); } // patch last pathPart with this attribute test pathParts.set(pathParts.size()-1,new XPath(""+sb,context)); return pathParts; } else { sb.append("self::").append(tok); pt.nextToken(); } if(pt.hasNext() && (tok=pt.getToken()).equals("[")){ // a predicate is encountered, gobble rest of expression in a single xp expression while(pt.hasNext()){ sb.append(pt.isString()?("\""+tok+"\""):tok); tok=pt.nextToken(); } pathParts.add(new XPath(""+sb,context)); return pathParts; } pathParts.add(new XPath(""+sb,context)); sb.setLength(0); } } catch (IOException e){ e.printStackTrace(); } catch (XPathFactoryConfigurationException e){ e.printStackTrace(); } return pathParts; } public String toString(){ StringBuilder sb=new StringBuilder(); for(XPath part:parts) sb.append(part); return ""+sb; } /** * @return the list of parts of expression */ public List getParts(){ return parts; } /** * For unit testing * @param args */ public static void main(String[] args){ // tester le parsing et l'affichage des patterns NamespaceContext nsc = new NamespaceContext(); for(String s:new String[]{ "/books/book/test[true()]/@b", "/books/book/test/@b", "/books/book/test/@b[.=1]", "/dubois/verbe/mot[@no='01']/text()[.=\"adoucir\"]", "/dubois/verbe[@id='3.2']/mot/text()[.=\"adoucir les coins\"]", "/dubois/test[verbe/mot[@no=1]]" }){ System.out.println(s); System.out.println(new XPathParts(s,nsc)); } } }