Index: tmp/org.txm.core/src/java/org/txm/xml/ToDoListHookActivator.java
===================================================================
--- tmp/org.txm.core/src/java/org/txm/xml/ToDoListHookActivator.java	(revision 2596)
+++ tmp/org.txm.core/src/java/org/txm/xml/ToDoListHookActivator.java	(revision 2597)
@@ -1,35 +0,0 @@
-package org.txm.xml;
-
-import java.io.IOException;
-import java.util.List;
-
-import javax.xml.stream.XMLStreamException;
-
-/**
- * To use if you have N elements to process with a specific localname for each one
- * 
- * @author mdecorde
- *
- */
-public class ToDoListHookActivator extends HookActivator {
-	
-	List<String> tasks;
-	
-	int current = 0;
-	
-	public ToDoListHookActivator(List<String> tasks) throws IOException, XMLStreamException {
-		this.tasks = tasks;
-	}
-	
-	@Override
-	public boolean mustActivate() {
-		if (tasks.size() <= current) return false;
-		
-		return tasks.get(current).equals(hook.getLocalName());
-	}
-	
-	@Override
-	public void hookWasActivated() {
-		current++;
-	}
-}
Index: tmp/org.txm.core/src/java/org/txm/xml/XPathsHookActivator.java
===================================================================
--- tmp/org.txm.core/src/java/org/txm/xml/XPathsHookActivator.java	(revision 0)
+++ tmp/org.txm.core/src/java/org/txm/xml/XPathsHookActivator.java	(revision 2597)
@@ -0,0 +1,133 @@
+package org.txm.xml;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.eclipse.osgi.util.NLS;
+import org.txm.utils.logger.Log;
+
+/**
+ * Simple "XPath without attribute selector" Activator activated when the current path matches the xpath
+ * 
+ * supported operators : / , // , * , node()
+ * only the last element attributes can be tested with simple equals test
+ * 
+ * exemple: //p[name='value']
+ * exemple: /text/node()/p[name='value']
+ * 
+ * @author mdecorde
+ *
+ */
+public class XPathsHookActivator extends XPathHookActivator {
+	
+	int currentXPath = 0;
+	List<String> xpaths;
+	
+	/**
+	 * @param localname the element localname to match
+	 */
+	public XPathsHookActivator(Hook hook, List<String> xpaths) {
+		super(hook, xpaths.get(0));
+		this.xpaths = xpaths;
+		
+		loadNextXPath();
+	}
+	
+	/**
+	 * the xpaths used to build the patterns
+	 */
+	public List<String> getXPaths() {
+		return xpaths;
+	}
+	
+	/**
+	 * 
+	 */
+	public int getCurrentXPathIndex() {
+		return currentXPath;
+	}
+	
+	/**
+	 * the xpaths used to build the patterns
+	 */
+	public String getCurrentXPath() {
+		if (xpaths.size() <= currentXPath) return null;
+		
+		return xpaths.get(currentXPath);
+	}
+	
+	protected boolean loadNextXPath() {
+		if (xpaths == null || xpaths.size() <= currentXPath) {
+			p = null;
+			return true; // nothing to load
+		}
+		
+		String xpath = xpaths.get(currentXPath);
+		String regex = xpath;
+		
+		int attrTest = xpath.indexOf("["); // [some tests]
+		int lastNodeTest = xpath.lastIndexOf("/");
+		
+		if (attrTest > 0 && attrTest > lastNodeTest) {
+			attributesTest = new LinkedHashMap<>();
+			regex = xpath.substring(0, attrTest);
+			String tail = xpath.substring(attrTest);
+			tail = tail.substring(1, tail.length() - 1);
+			if (debug) System.out.println("TAIL=" + tail);
+			String tests[] = tail.split("@");
+			if (debug) System.out.println("TESTS=" + Arrays.toString(tests));
+			for (String test : tests) {
+				if (test.length() == 0) continue;
+				
+				String split2[] = test.split("=", 2); // 0 name 1 "value"
+				if (debug) System.out.println("TEST=" + Arrays.toString(split2));
+				attributesTest.put(split2[0], split2[1].substring(1, split2[1].length() - 1));
+			}
+		}
+		
+		regex = regex.replaceAll("([^.])[*]", "$1[^/]+");
+		if (regex.startsWith("//")) regex = "(/[^/]+)*/" + regex.substring(2);
+		regex = regex.replace("//", "(/[^/]+)*/");
+		regex = regex.replace("node()", "[^/]+");
+		
+		try {
+			this.p = Pattern.compile(regex);
+			if (debug) System.out.println("P="+p);
+		} catch(PatternSyntaxException e) {
+			String m = NLS.bind("Pattern not compiled correctly with: {0} at {1}.", xpath+" ("+currentXPath+")", hook.getLocation());
+			Log.severe(m);
+			Log.severe("Pattern error: "+e);
+			Log.printStackTrace(e);
+			p = null;
+			return false;
+		}
+		
+		return true;
+	}
+	
+	public boolean hasAllXpathsBeenProcessed() {
+		return xpaths != null && xpaths.size() == currentXPath;
+	}
+	
+	@Override
+	public boolean mustActivate() {
+		boolean b = super.mustActivate();
+		if (b) {
+			currentXPath++;
+		}
+		return b;
+	}
+	
+	@Override
+	public void hookWasActivated() {
+		loadNextXPath();
+	}
+	
+	public static void main(String[] args) {
+		new XPathsHookActivator(null, 
+				Arrays.asList("//text//p[@name='value']", "//text//p[@name='value']"));
+	}
+}

Property changes on: tmp/org.txm.core/src/java/org/txm/xml/XPathsHookActivator.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: tmp/org.txm.core/src/java/org/txm/xml/DOMIdentityHook.java
===================================================================
--- tmp/org.txm.core/src/java/org/txm/xml/DOMIdentityHook.java	(revision 0)
+++ tmp/org.txm.core/src/java/org/txm/xml/DOMIdentityHook.java	(revision 2597)
@@ -0,0 +1,111 @@
+package org.txm.xml;
+
+import java.io.IOException;
+
+import javax.xml.stream.XMLStreamException;
+
+import org.txm.utils.xml.DomUtils;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class DOMIdentityHook extends Hook {
+
+	Element dom;
+	
+	public DOMIdentityHook(String name, HookActivator activator, XMLProcessor processor) throws IOException, XMLStreamException {
+		super(name, activator, processor);
+	}
+
+	@Override
+	public boolean _activate() {
+		StaxDomConstructor domConstructor = new StaxDomConstructor(parentParser.parser);
+		try {
+			dom = domConstructor.getDom();
+			return dom != null;
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			return false;
+		}
+	}
+	
+	@Override
+	public boolean mustDeactivate() {
+		boolean b = dom != null; // the DOM has been constructed and the XMLProcess can continue parsing
+		if (b) {
+			try {
+				writeDOM();
+				dom = null;
+			} catch (XMLStreamException e) {
+				e.printStackTrace();
+			}
+		}
+		return b;
+	}
+
+	@Override
+	public boolean deactivate() {
+		return dom == null; // dom should be null
+	}
+
+	private void writeDOM() throws XMLStreamException {
+		writeDOM(dom);
+	}
+	
+	private void writeDOM(Node node) throws XMLStreamException {
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			Element e = (Element)node;
+			NodeList children = e.getChildNodes();
+			if (children.getLength() > 0) {
+				parentParser.writer.writeStartElement(e.getNamespaceURI(), e.getLocalName());
+			} else {
+				parentParser.writer.writeEmptyElement(e.getNamespaceURI(),e.getLocalName());
+			}
+			
+			for (int i = 0 ; i < e.getAttributes().getLength() ; i++) {
+				Node att = e.getAttributes().item(i);
+				parentParser.writer.writeAttribute(att.getNamespaceURI(), att.getNodeName(), att.getNodeValue());
+			}
+			
+			for (int c = 0 ; c < children.getLength() ; c++) {
+				writeDOM(children.item(c));
+			}
+			if (children.getLength() > 0) {
+				parentParser.writer.writeEndElement();
+			}
+		} else if (node.getNodeType() == Node.TEXT_NODE) {
+			parentParser.writer.writeCharacters("T"+node.getTextContent());
+		}
+	}
+
+	@Override
+	protected void processNamespace() throws XMLStreamException { }
+
+	@Override
+	protected void processStartElement() throws XMLStreamException, IOException { }
+
+	@Override
+	protected void processCharacters() throws XMLStreamException { }
+
+	@Override
+	protected void processProcessingInstruction() throws XMLStreamException { }
+
+	@Override
+	protected void processDTD() throws XMLStreamException { }
+
+	@Override
+	protected void processCDATA() throws XMLStreamException { }
+
+	@Override
+	protected void processComment() throws XMLStreamException { }
+
+	@Override
+	protected void processEndElement() throws XMLStreamException { }
+
+	@Override
+	protected void processEndDocument() throws XMLStreamException { }
+
+	@Override
+	protected void processEntityReference() throws XMLStreamException { }
+}

Property changes on: tmp/org.txm.core/src/java/org/txm/xml/DOMIdentityHook.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: tmp/org.txm.core/src/java/org/txm/xml/HookActivator.java
===================================================================
--- tmp/org.txm.core/src/java/org/txm/xml/HookActivator.java	(revision 2596)
+++ tmp/org.txm.core/src/java/org/txm/xml/HookActivator.java	(revision 2597)
@@ -28,7 +28,7 @@
 	/**
 	 * Use this method if you need the activator to be updated when the hook was activated once
 	 */
-	public abstract void hookWasActivated();
+	protected abstract void hookWasActivated();
 	
 	/**
 	 * Set afterward the hook
Index: tmp/org.txm.core/src/java/org/txm/xml/Hook.java
===================================================================
--- tmp/org.txm.core/src/java/org/txm/xml/Hook.java	(revision 2596)
+++ tmp/org.txm.core/src/java/org/txm/xml/Hook.java	(revision 2597)
@@ -49,6 +49,9 @@
 	 */
 	public final boolean activate() {
 		elements = 0;
+		if (activator != null) {
+			activator.hookWasActivated();
+		}
 		return _activate();
 	}
 	
@@ -67,10 +70,11 @@
 	 */
 	public final boolean mustActivate() {
 		if (activator == null) return false;
+		
 		return activator.mustActivate();
 	}
 	
-	public final boolean mustDeactivate() {
+	public boolean mustDeactivate() {
 		return elements == 0;
 	}
 	
Index: tmp/org.txm.core/src/java/org/txm/xml/XMLProcessor.java
===================================================================
--- tmp/org.txm.core/src/java/org/txm/xml/XMLProcessor.java	(revision 2596)
+++ tmp/org.txm.core/src/java/org/txm/xml/XMLProcessor.java	(revision 2597)
@@ -6,6 +6,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Stack;
@@ -430,10 +431,6 @@
 	
 	protected void processStartElement() throws XMLStreamException, IOException {
 		String prefix = parser.getPrefix();
-		if (INCLUDE == localname && XI == prefix) {
-			processXInclude();
-		}
-		else {
 			if (prefix != null && prefix.length() > 0) {
 				writer.writeStartElement(Nscontext.getNamespaceURI(prefix), localname);
 			}
@@ -446,15 +443,10 @@
 			}
 			
 			writeAttributes();
-		}
 	}
 	
 	private void _processStartElement() throws XMLStreamException, IOException {
 		String prefix = parser.getPrefix();
-		if (INCLUDE == localname && XI == prefix) {
-			processXInclude();
-		}
-		else {
 			if (prefix != null && prefix.length() > 0) {
 				writer.writeStartElement(Nscontext.getNamespaceURI(prefix), localname);
 			}
@@ -466,7 +458,6 @@
 			}
 			
 			writeAttributes();
-		}
 	}
 	
 	private Stack<LinkedHashMap<String, String>> attributesStack = new Stack<>();
@@ -539,34 +530,6 @@
 		writer.writeEntityRef(parser.getLocalName());
 	}
 	
-	/**
-	 * Process the XInclude elements
-	 * 
-	 * @throws IOException
-	 * @throws XMLStreamException
-	 */
-	protected void processXInclude() throws XMLStreamException, IOException {
-		String url = parser.getAttributeValue(null, "href"); // relative only
-		File driver = new File(inputurl.getFile());
-		File ref = new File(driver.getParent(), url);
-		if (ref.exists()) {
-			URL includeurl = ref.toURI().toURL();
-			// save variables before killing them
-			System.out.println("process xi include: " + ref);
-			XMLStreamReader parserSave = this.parser; // back up current parser
-			InputStream xiIncludeInputData = includeurl.openStream();
-			XMLStreamReader xiIncludeParser = factory.createXMLStreamReader(xiIncludeInputData);
-			parser = xiIncludeParser;
-			processingXInclude++; // to avoid recalling before & after methods
-			this.process(writer);
-			processingXInclude--; // end of XInclude processing
-			this.parser = parserSave; // restore parser
-		}
-		else {
-			System.out.println("Warning referenced file: $ref does not exists");
-		}
-	}
-	
 	public String getCurrentPath() {
 		return currentXPath.toString();
 	}
@@ -603,31 +566,37 @@
 			// parentParser.writer.writeAttribute("hook", name);
 			// }
 			// };
+			XPathHookActivator xpathActivator = new XPathHookActivator(null, "//p");
+			XPathsHookActivator xpathsActivator = new XPathsHookActivator(null, Arrays.asList("//p", "//p"));
+//			IdentityHook hook2 = new IdentityHook("hook2", xpathsActivator, builder) {
+//				
+//				@Override
+//				public boolean _activate() {
+//					System.out.println("ACTIVATING " + name + " AT " + getLocation());
+//					return true;
+//				}
+//				
+//				@Override
+//				public boolean deactivate() {
+//					System.out.println("DEACTIVATING " + name + " AT " + getLocation());
+//					return true;
+//				}
+//				
+//				@Override
+//				public void processStartElement() throws XMLStreamException, IOException {
+//					super.processStartElement();
+//					parentParser.writer.writeAttribute("hook", name);
+//				}
+//			};
 			
-			IdentityHook hook2 = new IdentityHook("hook2", new XPathHookActivator(null, "//language[@ident='fr']"), builder) {
-				
-				@Override
-				public boolean _activate() {
-					System.out.println("ACTIVATING " + name + " AT " + getLocation());
-					return true;
-				}
-				
-				@Override
-				public boolean deactivate() {
-					System.out.println("DEACTIVATING " + name + " AT " + getLocation());
-					return true;
-				}
-				
-				@Override
-				public void processStartElement() throws XMLStreamException, IOException {
-					super.processStartElement();
-					parentParser.writer.writeAttribute("hook", name);
-				}
+			DOMIdentityHook hook3 = new DOMIdentityHook("hook3", xpathsActivator, builder) {
+
 			};
 			
 			long time = System.currentTimeMillis();
 			if (builder.process(output)) {
 				System.out.println("Time=" + (System.currentTimeMillis() - time));
+				System.out.println("XPaths activator has done working ? "+xpathsActivator.hasAllXpathsBeenProcessed());
 			}
 			else {
 				System.out.println("failure !");
Index: tmp/org.txm.core/src/java/org/txm/xml/XPathHookActivator.java
===================================================================
--- tmp/org.txm.core/src/java/org/txm/xml/XPathHookActivator.java	(revision 2596)
+++ tmp/org.txm.core/src/java/org/txm/xml/XPathHookActivator.java	(revision 2597)
@@ -25,7 +25,7 @@
 	LinkedHashMap<String, String> attributesTest = null;
 	
 	
-	private boolean debug = false;
+	protected boolean debug = false;
 	
 	/**
 	 * @param localname the element localname to match
@@ -67,13 +67,14 @@
 	@Override
 	public boolean mustActivate() {
 		if (xpath == null) return false;
+		if (p == null) return false;
 		
-		// System.out.println(hook.getCurrentPath() + hook.parentParser.getCurrentAttributes());
+		if (debug) System.out.println(hook.getCurrentPath() + hook.parentParser.getCurrentAttributes());
 		if (attributesTest != null) {
-			return p.matcher(hook.getCurrentPath()).find() && hook.parentParser.getCurrentAttributes().equals(attributesTest);
+			return p.matcher(hook.getCurrentPath()).matches() && hook.parentParser.getCurrentAttributes().equals(attributesTest);
 		}
 		else {
-			return p.matcher(hook.getCurrentPath()).find();
+			return p.matcher(hook.getCurrentPath()).matches();
 		}
 	}
 	
