|
From: <pm_...@us...> - 2012-02-07 08:53:57
|
Revision: 4520
http://mxquery.svn.sourceforge.net/mxquery/?rev=4520&view=rev
Author: pm_fischer
Date: 2012-02-07 08:53:50 +0000 (Tue, 07 Feb 2012)
Log Message:
-----------
- Use AbstractStep objects throughout the plan
- Properly implement projection for count() and data()
- Loading should work for a single, child-only path, local names
Modified Paths:
--------------
trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/CountIterator.java
trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/DataValuesIterator.java
trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/Doc.java
trunk/MXQuery/src/ch/ethz/mxquery/iterators/AttributeIterator.java
trunk/MXQuery/src/ch/ethz/mxquery/iterators/ChildIterator.java
trunk/MXQuery/src/ch/ethz/mxquery/iterators/DescendantOrSelfIterator.java
trunk/MXQuery/src/ch/ethz/mxquery/iterators/XMLContent.java
trunk/MXQuery/src/ch/ethz/mxquery/model/AbstractStep.java
trunk/MXQuery/src/ch/ethz/mxquery/xdmio/xmlAdapters/NonValidatingStaxAdapterProjection.java
Modified: trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/CountIterator.java
===================================================================
--- trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/CountIterator.java 2012-02-07 08:51:38 UTC (rev 4519)
+++ trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/CountIterator.java 2012-02-07 08:53:50 UTC (rev 4520)
@@ -27,10 +27,13 @@
import ch.ethz.mxquery.datamodel.xdm.LongToken;
import ch.ethz.mxquery.datamodel.xdm.TokenInterface;
import ch.ethz.mxquery.exceptions.MXQueryException;
+import ch.ethz.mxquery.exceptions.StaticException;
import ch.ethz.mxquery.iterators.VariableIterator;
import ch.ethz.mxquery.model.IndexIterator;
import ch.ethz.mxquery.model.TokenBasedIterator;
import ch.ethz.mxquery.model.XDMIterator;
+import ch.ethz.mxquery.util.ObjectObjectPair;
+import ch.ethz.mxquery.util.Set;
public class CountIterator extends TokenBasedIterator {
private IndexIterator indexIter;
@@ -107,4 +110,15 @@
copy.setSubIters(subIters);
return copy;
}
+
+ public ObjectObjectPair getProjectionPaths() throws StaticException {
+ Set returned = new Set();
+ Set used = new Set();
+ ObjectObjectPair cur = subIters[0].getProjectionPaths();
+ // Conditionals used and returned go to to used
+ used.addAll((Set)cur.getFirst());
+ used.addAll((Set)cur.getSecond());
+ return new ObjectObjectPair(returned, used);
+ }
+
}
Modified: trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/DataValuesIterator.java
===================================================================
--- trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/DataValuesIterator.java 2012-02-07 08:51:38 UTC (rev 4519)
+++ trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/DataValuesIterator.java 2012-02-07 08:53:50 UTC (rev 4520)
@@ -15,6 +15,7 @@
package ch.ethz.mxquery.functions.fn;
+import java.util.Enumeration;
import java.util.Vector;
import org.apache.xerces.xs.ShortList;
@@ -35,15 +36,19 @@
import ch.ethz.mxquery.exceptions.ErrorCodes;
import ch.ethz.mxquery.exceptions.MXQueryException;
import ch.ethz.mxquery.exceptions.QueryLocation;
+import ch.ethz.mxquery.exceptions.StaticException;
import ch.ethz.mxquery.exceptions.TypeException;
import ch.ethz.mxquery.functions.Function;
import ch.ethz.mxquery.functions.xs.XSConstructorIterator;
import ch.ethz.mxquery.functions.xs.XSQName;
import ch.ethz.mxquery.iterators.SequenceIterator;
import ch.ethz.mxquery.iterators.TokenIterator;
+import ch.ethz.mxquery.model.AbstractStep;
import ch.ethz.mxquery.model.CurrentBasedIterator;
import ch.ethz.mxquery.model.EmptySequenceIterator;
import ch.ethz.mxquery.model.XDMIterator;
+import ch.ethz.mxquery.util.ObjectObjectPair;
+import ch.ethz.mxquery.util.Set;
import ch.ethz.mxquery.util.Utils;
public class DataValuesIterator extends CurrentBasedIterator {
@@ -743,4 +748,26 @@
copy.setContext(context, false);
return copy;
}
+
+ public ObjectObjectPair getProjectionPaths() throws StaticException {
+ Set returned = new Set();
+ Set used = new Set();
+
+ if (subIters != null)
+ for (int i=0;i<subIters.length;i++){
+ ObjectObjectPair cur = subIters[i].getProjectionPaths();
+ Enumeration returnedPaths = ((Set)cur.getFirst()).elements();
+ while (returnedPaths.hasMoreElements()) {
+ Vector curRetPath = (Vector)returnedPaths.nextElement();
+ Vector res = new Vector();
+ res.addAll(curRetPath);
+ res.addElement(AbstractStep.KEEP_SUBTREE);
+ used.add(res);
+ }
+ used.addAll((Set)cur.getSecond());
+ }
+ return new ObjectObjectPair(returned, used);
+
+ }
+
}
Modified: trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/Doc.java
===================================================================
--- trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/Doc.java 2012-02-07 08:51:38 UTC (rev 4519)
+++ trunk/MXQuery/src/ch/ethz/mxquery/functions/fn/Doc.java 2012-02-07 08:53:50 UTC (rev 4520)
@@ -30,6 +30,7 @@
import ch.ethz.mxquery.exceptions.MXQueryException;
import ch.ethz.mxquery.functions.RequestTypeMulti;
import ch.ethz.mxquery.iterators.TokenIterator;
+import ch.ethz.mxquery.model.AbstractStep;
import ch.ethz.mxquery.model.CurrentBasedIterator;
import ch.ethz.mxquery.model.EmptySequenceIterator;
import ch.ethz.mxquery.model.TokenSequenceIterator;
@@ -256,7 +257,9 @@
public ObjectObjectPair getProjectionPaths() {
Set returned = new Set();
- returned.add("/");
+ Vector rPath = new Vector();
+ rPath.addElement(AbstractStep.ROOT_STEP);
+ returned.add(rPath);
return new ObjectObjectPair(returned, new Set());
}
Modified: trunk/MXQuery/src/ch/ethz/mxquery/iterators/AttributeIterator.java
===================================================================
--- trunk/MXQuery/src/ch/ethz/mxquery/iterators/AttributeIterator.java 2012-02-07 08:51:38 UTC (rev 4519)
+++ trunk/MXQuery/src/ch/ethz/mxquery/iterators/AttributeIterator.java 2012-02-07 08:53:50 UTC (rev 4520)
@@ -30,6 +30,7 @@
import ch.ethz.mxquery.exceptions.QueryLocation;
import ch.ethz.mxquery.exceptions.StaticException;
import ch.ethz.mxquery.exceptions.TypeException;
+import ch.ethz.mxquery.model.AbstractStep;
import ch.ethz.mxquery.model.StepInformation;
import ch.ethz.mxquery.model.CheckNodeType;
import ch.ethz.mxquery.model.CurrentBasedIterator;
@@ -181,16 +182,10 @@
Set returned = new Set();
Enumeration pathEnum = returnedBelow.elements();
while (pathEnum.hasMoreElements()) {
- String res = (String) pathEnum.nextElement();
- if (res.endsWith("/"))
- res = res.substring(0, res.length()-1);
- if (namespace != null)
- res = res+"/@{"+namespace+"}:";
- if (local != null) {
- if (namespace == null)
- res = res+"/@";
- res = res+local;
- }
+ Vector prev = (Vector) pathEnum.nextElement();
+ Vector res = new Vector();
+ res.addAll(prev);
+ res.addElement(new AbstractStep(AXIS_ATTRIBUTE, stepData));
returned.add(res);
}
return new ObjectObjectPair(returned, paths.getSecond());
Modified: trunk/MXQuery/src/ch/ethz/mxquery/iterators/ChildIterator.java
===================================================================
--- trunk/MXQuery/src/ch/ethz/mxquery/iterators/ChildIterator.java 2012-02-07 08:51:38 UTC (rev 4519)
+++ trunk/MXQuery/src/ch/ethz/mxquery/iterators/ChildIterator.java 2012-02-07 08:53:50 UTC (rev 4520)
@@ -39,6 +39,7 @@
import ch.ethz.mxquery.model.Window;
import ch.ethz.mxquery.model.XDMIterator;
import ch.ethz.mxquery.util.KXmlSerializer;
+import ch.ethz.mxquery.util.LogLevel;
import ch.ethz.mxquery.util.ObjectObjectPair;
import ch.ethz.mxquery.util.Set;
@@ -271,8 +272,13 @@
Set returned = new Set();
Enumeration pathEnum = returnedBelow.elements();
while (pathEnum.hasMoreElements()) {
- Vector res = (Vector) pathEnum.nextElement();
- res.addElement(new AbstractStep(AXIS_CHILD, stepData));
+ Vector res = new Vector();
+ Vector prev = (Vector) pathEnum.nextElement();
+ res.addAll(prev);
+ if (stepData.getXQName() != null)
+ res.addElement(new AbstractStep(AXIS_CHILD, stepData));
+ else
+ logger.log(LogLevel.FINE, "Projection Paths for non-named nodetests currently not supported");
returned.add(res);
}
return new ObjectObjectPair(returned, paths.getSecond());
Modified: trunk/MXQuery/src/ch/ethz/mxquery/iterators/DescendantOrSelfIterator.java
===================================================================
--- trunk/MXQuery/src/ch/ethz/mxquery/iterators/DescendantOrSelfIterator.java 2012-02-07 08:51:38 UTC (rev 4519)
+++ trunk/MXQuery/src/ch/ethz/mxquery/iterators/DescendantOrSelfIterator.java 2012-02-07 08:53:50 UTC (rev 4520)
@@ -462,7 +462,9 @@
Set returned = new Set();
Enumeration pathEnum = returnedBelow.elements();
while (pathEnum.hasMoreElements()) {
- Vector res = (Vector) pathEnum.nextElement();
+ Vector prev = (Vector) pathEnum.nextElement();
+ Vector res = new Vector();
+ res.addAll(prev);
res.addElement(new AbstractStep(descAxis, stepData));
returned.add(res);
}
Modified: trunk/MXQuery/src/ch/ethz/mxquery/iterators/XMLContent.java
===================================================================
--- trunk/MXQuery/src/ch/ethz/mxquery/iterators/XMLContent.java 2012-02-07 08:51:38 UTC (rev 4519)
+++ trunk/MXQuery/src/ch/ethz/mxquery/iterators/XMLContent.java 2012-02-07 08:53:50 UTC (rev 4520)
@@ -42,6 +42,7 @@
import ch.ethz.mxquery.exceptions.QueryLocation;
import ch.ethz.mxquery.exceptions.StaticException;
import ch.ethz.mxquery.exceptions.TypeException;
+import ch.ethz.mxquery.model.AbstractStep;
import ch.ethz.mxquery.model.Iterator;
import ch.ethz.mxquery.model.XDMIterator;
import ch.ethz.mxquery.util.KXmlSerializer;
@@ -618,8 +619,11 @@
ObjectObjectPair cur = subIters[i].getProjectionPaths();
Enumeration returnedPaths = ((Set)cur.getFirst()).elements();
while (returnedPaths.hasMoreElements()) {
- String curRetPath = (String)returnedPaths.nextElement();
- used.add(curRetPath+" #");
+ Vector curRetPath = (Vector)returnedPaths.nextElement();
+ Vector res = new Vector();
+ res.addAll(curRetPath);
+ res.addElement(AbstractStep.KEEP_SUBTREE);
+ used.add(res);
}
used.addAll((Set)cur.getSecond());
}
Modified: trunk/MXQuery/src/ch/ethz/mxquery/model/AbstractStep.java
===================================================================
--- trunk/MXQuery/src/ch/ethz/mxquery/model/AbstractStep.java 2012-02-07 08:51:38 UTC (rev 4519)
+++ trunk/MXQuery/src/ch/ethz/mxquery/model/AbstractStep.java 2012-02-07 08:53:50 UTC (rev 4520)
@@ -49,6 +49,10 @@
else
return "attribute::";
+ case AXIS_DESCENDANT:
+ return "descendant::";
+ case 99:
+ return "#";
default:
throw new RuntimeException();
}
Modified: trunk/MXQuery/src/ch/ethz/mxquery/xdmio/xmlAdapters/NonValidatingStaxAdapterProjection.java
===================================================================
--- trunk/MXQuery/src/ch/ethz/mxquery/xdmio/xmlAdapters/NonValidatingStaxAdapterProjection.java 2012-02-07 08:51:38 UTC (rev 4519)
+++ trunk/MXQuery/src/ch/ethz/mxquery/xdmio/xmlAdapters/NonValidatingStaxAdapterProjection.java 2012-02-07 08:53:50 UTC (rev 4520)
@@ -13,11 +13,43 @@
* limitations under the License.
*/
+
+/*
+ * Contains the document projection logic outlined in the Marian/Simeon paper:
+ * Automaton to express what to do with the current event
+ * KEEP: this node (but not its descendants) should be kept
+ * KEEP_SUB: this node and its descendants should be kept
+ * SKIP: the current node/event should be discarded
+ * MOVE: the current node/event is on a projection path, but not at its end. It may have to be kept if we match a KEEP/KEEP_SUB node at the end of this path
+ *
+ * We keep track of the level on which we switched to SKIP/SUB_KEEP: top skip, top keep node => skipKeepLevel
+ *
+ * Transitions:
+ *
+ * Driven by opening tags
+ * MOVE->KEEP: We reach the end of a projection path, match the name and do not keep descendants => produce
+ * MOVE->KEEP_SUB: end of projection path with
+ * MOVE->SKIP: At some of the projection path, we do not match the name
+ * KEEP->SKIP: produced the kept node, go "deeper"
+ * MOVE->MOVE: on a projection path, match name
+ * SKIP->SKIP: any opening tag
+ * KEEP_SUB->KEEP_SUB: any opening tag
+ *
+ * Driven by closing tags
+ * SKIP->KEEP: reached skipKeepLevel, level above matched
+ * SKIP->MOVE: reached skipKeepLevel, level above did not match
+ * KEEP->MOVE: produced the closing tag of kept node
+ * KEEP_SUB->MOVE: reached skipKeepLevel
+ * MOVE->MOVE: on a projection path, match name close
+ * SKIP->SKIP: any closing tag greater than skipKeepLevel
+ * KEEP_SUB->KEEP_SUB: any closing tag greater than skipKeepLevel
+ */
package ch.ethz.mxquery.xdmio.xmlAdapters;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Vector;
+import java.util.Stack;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
@@ -39,8 +71,8 @@
import ch.ethz.mxquery.exceptions.QueryLocation;
import ch.ethz.mxquery.model.AbstractStep;
import ch.ethz.mxquery.model.XDMIterator;
-import ch.ethz.mxquery.util.Utils;
+
public class NonValidatingStaxAdapterProjection extends XDMImportAdapter {
private XMLStreamReader reader;
@@ -50,20 +82,27 @@
private int [] projPathPos;
+ private Stack bufferedPathName;
+ private Stack bufferedPathURI;
+ private Stack bufferedPathPrefix;
+ private Stack bufferedAttributes;
+
+ private int pathProducedLevel = 0;
+
int skipKeepLevel = -1;
- private int PROJ_MODE_NORMAL = 0;
- private int PROJ_MODE_SKIP = 1;
- private int PROJ_MODE_KEEP_SUB = 2;
- private int PROJ_MODE_KEEP = 3;
- private int PROJ_MODE_MOVE = 4;
+ private final int PROJ_MODE_SKIP = 1;
+ private final int PROJ_MODE_KEEP_SUB = 2;
+ private final int PROJ_MODE_KEEP = 3;
+ private final int PROJ_MODE_MOVE = 4;
- int curProjMode = PROJ_MODE_NORMAL;
+ int curProjMode = PROJ_MODE_MOVE;
public NonValidatingStaxAdapterProjection(Context ctx, QueryLocation loc, XMLStreamReader reader) {
super(ctx, loc);
this.reader = reader;
this.tokensList = new LinkedList();
+ this.bufferedPathName = new Stack();
}
private TokenInterface getNext() {
@@ -82,11 +121,10 @@
case XMLStreamConstants.CHARACTERS:
case XMLStreamConstants.SPACE:
{
- if (curProjMode == PROJ_MODE_SKIP) {
+ if (curProjMode == PROJ_MODE_SKIP || curProjMode == PROJ_MODE_MOVE) {
reader.next();
continue;
}
-
StringBuffer mergedText = new StringBuffer();
while (event == XMLStreamConstants.CDATA || event == XMLStreamConstants.SPACE || event == XMLStreamConstants.CHARACTERS) {
mergedText.append(reader.getText());
@@ -96,7 +134,7 @@
return new TextToken(Type.TEXT_NODE_UNTYPED_ATOMIC, createNextTokenId(Type.TEXT_NODE_UNTYPED_ATOMIC, null), mergedText.toString(),curNsScope);
}
case XMLStreamConstants.COMMENT:
- if (curProjMode == PROJ_MODE_SKIP)
+ if (curProjMode == PROJ_MODE_SKIP || curProjMode == PROJ_MODE_MOVE)
continue;
tok = new CommentToken(createNextTokenId(Type.COMMENT, null), reader.getText(),curNsScope);
@@ -104,54 +142,120 @@
case XMLStreamConstants.END_DOCUMENT:
tok = new Token(Type.END_DOCUMENT,null,curNsScope);
break;
- case XMLStreamConstants.END_ELEMENT:
- String name = reader.getLocalName();
- String ns_uri = reader.getNamespaceURI();
- String prefix = reader.getPrefix();
- if (prefix != null && prefix.length() == 0)
- prefix = null;
- //
- boolean stillSkip = false;
- if (curProjMode == PROJ_MODE_SKIP && level == skipKeepLevel) {
- curProjMode = PROJ_MODE_KEEP;
- skipKeepLevel = -1;
- stillSkip = true;
- }
- if (curProjMode == PROJ_MODE_KEEP && projPathPos[0] > 0) {
- XQName curPathCheck = ((AbstractStep) ((Vector)projectionPaths.get(0)).elementAt(projPathPos[0])).getNodeTest().getXQName();
- if (curPathCheck.getLocalPart().equals(name)) { //TODO: Handle namespaces
- projPathPos[0]--;
+ case XMLStreamConstants.END_ELEMENT: {
+ boolean emitTag = false;
+ String name_debug = reader.getLocalName();
+ switch (curProjMode) {
+ case PROJ_MODE_KEEP_SUB:
+ //KEEP_SUB->MOVE: reached skipKeepLevel
+ //KEEP_SUB->KEEP_SUB: any closing tag greater than skipKeepLevel
+ if (skipKeepLevel == level) {
+ curProjMode = PROJ_MODE_MOVE;
+ skipKeepLevel = -1;
+ pathProducedLevel--;
+ }
+ emitTag = true;
+ break;
+ case PROJ_MODE_SKIP:
+ // go to "KEEP", check later if we keep or move
+
+ if (skipKeepLevel == level+1) {
+ curProjMode = PROJ_MODE_MOVE;
+ if (pathProducedLevel >= level) {
+ emitTag = true;
+ pathProducedLevel--;
}
- if (projPathPos[0]+2 >= ((Vector)projectionPaths.get(0)).size())
- stillSkip = false;
- }
+ skipKeepLevel = -1;
+ }
+ else
+ if (skipKeepLevel == level) {
+ String name = reader.getLocalName();
+
+ Vector path = (Vector)projectionPaths.get(0);
- if (curProjMode == PROJ_MODE_MOVE && projPathPos[0] > 0) {
+ XQName curPathCheck = ((AbstractStep) (path).elementAt(projPathPos[0])).getNodeTest().getXQName();
+ if (curPathCheck.getLocalPart().equals(name) || level != projPathPos[0]) {
+ curProjMode = PROJ_MODE_KEEP;
+ } else {
+ curProjMode = PROJ_MODE_MOVE;
+ }
+ skipKeepLevel = -1;
+ }
+ else {
+ reader.next();
+ level--;
+ continue;
+ }
+ break;
+ case PROJ_MODE_MOVE: {
+ String name = reader.getLocalName();
XQName curPathCheck = ((AbstractStep) ((Vector)projectionPaths.get(0)).elementAt(projPathPos[0]-1)).getNodeTest().getXQName();
- if (curPathCheck.getLocalPart().equals(name)) { //TODO: Handle namespaces
- projPathPos[0]--;
- }
- }
-
- if (curProjMode == PROJ_MODE_KEEP_SUB && level == skipKeepLevel-1) {
- XQName curPathCheck = ((AbstractStep) ((Vector)projectionPaths.get(0)).elementAt(projPathPos[0]-1)).getNodeTest().getXQName();
if (!curPathCheck.getLocalPart().equals(name))
throw new MXQueryException(ErrorCodes.A0007_EC_IO, "Inconsistency in projecting, expected "+curPathCheck.getLocalPart()+" saw "+name, loc);
- curProjMode = PROJ_MODE_MOVE;
- skipKeepLevel = -1;
- projPathPos[0]-=2; // go back from the "keep" pseudo node
+
+ if (pathProducedLevel >= level) {
+ emitTag = true;
+ pathProducedLevel--;
+ }
+ projPathPos[0]--;
+ bufferedPathName.pop();
+ } break;
+ case PROJ_MODE_KEEP: {
+
+ //decide if keep or move directly, when we came from SKIP
+ //SKIP->KEEP: reached skipKeepLevel, level above matched
+ // SKIP->MOVE: reached skipKeepLevel, level above did not match
+ String name = reader.getLocalName();
+
+ Vector path = (Vector)projectionPaths.get(0);
+
+ if (path.size() == projPathPos[0]+1) {// last element in path, and not a "KEEP"
+ // really keep
+ emitTag = true;
+ } else {
+ curProjMode = PROJ_MODE_MOVE;
+ if (bufferedPathName.size() > level && bufferedPathName.get(level).equals(name)) {
+ emitTag = true;
+
+ }
+ bufferedPathName.pop();
+ projPathPos[0]--;
+ }
+ XQName curPathCheck = ((AbstractStep) (path).elementAt(projPathPos[0])).getNodeTest().getXQName();
+ if (!curPathCheck.getLocalPart().equals(name))
+ throw new MXQueryException(ErrorCodes.A0007_EC_IO, "Inconsistency in projecting, expected "+curPathCheck.getLocalPart()+" saw "+name, loc);
+ //projPathPos[0]--;
+ curProjMode = PROJ_MODE_MOVE;
+
+ pathProducedLevel--;
}
- if (curProjMode != PROJ_MODE_SKIP && !stillSkip) {
+
+ /*
+ * KEEP->MOVE: produced the closing tag of kept node
+ * MOVE->MOVE: on a projection path, match name close
+ * SKIP->SKIP: any closing tag greater than skipKeepLevel
+ */
+ }
+
+
+ //
+ if (emitTag) {
+ String name = reader.getLocalName();
+ String ns_uri = reader.getNamespaceURI();
+ String prefix = reader.getPrefix();
+ if (prefix != null && prefix.length() == 0)
+ prefix = null;
XQName tName = new QName(ns_uri, prefix, name);
tok = new ElementToken(Type.END_TAG, null, tName, curNsScope);
checkCloseNsScope();
- stillSkip = false;
- }
- level--;
- if (curProjMode == PROJ_MODE_SKIP || stillSkip) {
+ level--;
+ } else {
reader.next();
+ level--;
continue;
}
+
+ }
break;
case XMLStreamConstants.ENTITY_DECLARATION: // not used
break;
@@ -160,12 +264,12 @@
case XMLStreamConstants.NAMESPACE:
break;
case XMLStreamConstants.NOTATION_DECLARATION:
- if (curProjMode == PROJ_MODE_SKIP)
+ if (curProjMode == PROJ_MODE_SKIP || curProjMode == PROJ_MODE_MOVE)
continue;
tok = new TextToken(createNextTokenId(Type.NOTATION, null), reader.getText());
break;
case XMLStreamConstants.PROCESSING_INSTRUCTION:
- if (curProjMode == PROJ_MODE_SKIP)
+ if (curProjMode == PROJ_MODE_SKIP || curProjMode == PROJ_MODE_MOVE)
continue;
tok = new ProcessingInstrToken(createNextTokenId(Type.PROCESSING_INSTRUCTION, null), reader.getPIData(), reader.getPITarget(),curNsScope);
break;
@@ -180,7 +284,7 @@
break;
case XMLStreamConstants.START_ELEMENT:
level++;
-
+ // "shortcut": if we skip, we do not even have to retrieve names etc
if (curProjMode == PROJ_MODE_SKIP) {
reader.next();
continue;
@@ -193,112 +297,151 @@
String [] xmlIdREFS = null;
boolean createdNSScope = false;
- name = reader.getLocalName();
- ns_uri = reader.getNamespaceURI();
- prefix = reader.getPrefix();
-
+ String name = reader.getLocalName();
+ String ns_uri = reader.getNamespaceURI();
+ String prefix = reader.getPrefix();
+ if (prefix != null && prefix.length() == 0)
+ prefix = null;
+
// projection:
+ boolean emitTag = false;
+
// check if node name fits with currently active paths
- boolean skipOnNext = false;
- as = ((AbstractStep) ((Vector)projectionPaths.get(0)).elementAt(projPathPos[0]));
- if (as == AbstractStep.KEEP_SUBTREE) {
- curProjMode = PROJ_MODE_KEEP_SUB;
- skipKeepLevel = level;
- }
- else {
- XQName curPathCheck = as.getNodeTest().getXQName();
- if (curPathCheck.getLocalPart().equals(name)) { //TODO: Handle namespaces
- if (((Vector)projectionPaths.get(0)).size() <= projPathPos[0]+1) {
- curProjMode = PROJ_MODE_SKIP;
- skipOnNext = true;
- skipKeepLevel = level;
- }
- else {
- projPathPos[0]++;
- curProjMode = PROJ_MODE_MOVE;
- }
+ switch (curProjMode) {
+ case PROJ_MODE_KEEP_SUB:
+ emitTag = true; // no check, just output
+ break;
- } else {
- curProjMode = PROJ_MODE_SKIP;
- skipKeepLevel = level;
+ case PROJ_MODE_MOVE:
+ as = ((AbstractStep) ((Vector)projectionPaths.get(0)).elementAt(projPathPos[0]));
+ if (as == AbstractStep.KEEP_SUBTREE) {
+ curProjMode = PROJ_MODE_KEEP_SUB;
+ skipKeepLevel = level;
+ emitTag = true;
+ } else {
+ XQName curPathCheck = as.getNodeTest().getXQName();
+ if (curPathCheck.getLocalPart().equals(name)) { //TODO: Handle namespaces
+ // check name: if true, then either keep or move
+ Vector path = ((Vector)projectionPaths.get(0));
+ if (path.size() <= projPathPos[0]+1) {
+ tok = extractPendingElements(
+ name,
+ ns_uri,
+ prefix);
+ curProjMode = PROJ_MODE_KEEP;
+ skipKeepLevel = level+1;
+ }
+ else if (path.elementAt(path.size()-1)==AbstractStep.KEEP_SUBTREE && path.size() <= projPathPos[0]+2) {
+ tok = extractPendingElements(
+ name,
+ ns_uri,
+ prefix);
+ curProjMode = PROJ_MODE_KEEP_SUB;
+ skipKeepLevel = level;
+ }
+ else {
+ projPathPos[0]++;
+ curProjMode = PROJ_MODE_MOVE;
+ bufferedPathName.push(name);
+ reader.next();
+ continue; //buffer contents until we find a projection result
+ }
+
+ } else { // otherwise go to skip
+ skipKeepLevel = level;
+ curProjMode = PROJ_MODE_SKIP;
+ }
+ }
+
+ break;
+ case PROJ_MODE_KEEP: {
+ //emitTag = true;
+ skipKeepLevel = level;
+ curProjMode = PROJ_MODE_SKIP;
+ }
+ break;
+ // we handled SKIP already above
}
- }
- if (curProjMode == PROJ_MODE_SKIP && !skipOnNext) {
+ if (curProjMode == PROJ_MODE_SKIP) {
reader.next();
continue;
}
- if (prefix != null && prefix.length() == 0)
+ if (emitTag) {
+ if (prefix != null && prefix.length() == 0)
prefix = null;
- XQName tName = new QName(ns_uri, prefix, name);
- tok = new ElementToken(Type.START_TAG, createNextTokenId(Type.START_TAG, tName.toString()), tName, curNsScope);
-
- for (int i = 0; i < reader.getNamespaceCount(); i++) {
- String namespacePrefix = reader.getNamespacePrefix(i);
- String namespaceUri = reader.getNamespaceURI(i);
- XQName q;
- if (namespacePrefix == null)
- q = new QName(null, "xmlns");
- else
- q = new QName("xmlns", namespacePrefix);
- boolean newOpened = checkOpenNsScopeAddNs(createdNSScope, q, namespaceUri);
- if (newOpened && !createdNSScope)
- tok = new ElementToken(Type.START_TAG, tok.getNodeId(), tName, curNsScope);
+ XQName tName = new QName(ns_uri, prefix, name);
+ tok = new ElementToken(Type.START_TAG, createNextTokenId(Type.START_TAG, tName.toString()), tName, curNsScope);
}
+ if (curProjMode == PROJ_MODE_KEEP)
+ curProjMode = PROJ_MODE_SKIP;
+// TODO: restore namespace and attribute processing
+// for (int i = 0; i < reader.getNamespaceCount(); i++) {
+// String namespacePrefix = reader.getNamespacePrefix(i);
+// String namespaceUri = reader.getNamespaceURI(i);
+// XQName q;
+// if (namespacePrefix == null)
+// q = new QName(null, "xmlns");
+// else
+// q = new QName("xmlns", namespacePrefix);
+// boolean newOpened = checkOpenNsScopeAddNs(createdNSScope, q, namespaceUri);
+// if (newOpened && !createdNSScope)
+// tok = new ElementToken(Type.START_TAG, tok.getNodeId(), tName, curNsScope);
+// }
- for (int i = 0, n = reader.getAttributeCount(); i < n; ++i) {
- javax.xml.namespace.QName qName = reader.getAttributeName(i);
- name = qName.getLocalPart();
- ns_uri = qName.getNamespaceURI();
- prefix = qName.getPrefix();
-
-
-
- if (prefix.length() == 0)
- prefix = null;
- XQName q = new QName(ns_uri, prefix, name);
- String value = reader.getAttributeValue(i);
-
- String attType = reader.getAttributeType(i);
-
- if (!foundId && (attType.equals("ID") || isXMLId(tName,q))) {
- foundId = true;
- xmlId = value;
- }
- if (!foundIdREFS && (attType.equals("IDREF") || isIDREF(tName,q))) {
- foundIdREFS = true;
- xmlIdREFS = new String[]{value};
- }
-
- if (!foundIdREFS && (attType.equals("IDREFS") || isIDREFS(tName,q))) {
- foundIdREFS = true;
- xmlIdREFS = Utils.split(value," ", false);
- }
-
-
- boolean newOpened = checkOpenNsScopeAddNs(createdNSScope, q, value);
- if (newOpened && !createdNSScope)
- tok = new ElementToken(Type.START_TAG, tok.getNodeId(), tName, curNsScope);
-
- if (q.getNamespacePrefix() == null || q.getNamespacePrefix().equals("")) {
- if (q.getLocalPart().equals("xmlns"))
- continue;
- } else if (q.getNamespacePrefix().equals("xmlns"))
- continue;
- NamedToken attToken = createAttributeToken(Type.UNTYPED_ATOMIC, value, q, curNsScope);
- tokensList.add(attToken);
-
- if (foundId) {
- NamedToken nmToken = (NamedToken) tok ;
- nmToken.setID(xmlId);
- }
- if (foundIdREFS) {
- NamedToken nmToken = (NamedToken) tok;
- nmToken.setIDREFS(xmlIdREFS);
- }
-
-
- }
+// for (int i = 0, n = reader.getAttributeCount(); i < n; ++i) {
+// javax.xml.namespace.QName qName = reader.getAttributeName(i);
+// name = qName.getLocalPart();
+// ns_uri = qName.getNamespaceURI();
+// prefix = qName.getPrefix();
+//
+//
+//
+// if (prefix.length() == 0)
+// prefix = null;
+// XQName q = new QName(ns_uri, prefix, name);
+// String value = reader.getAttributeValue(i);
+//
+// String attType = reader.getAttributeType(i);
+//
+// if (!foundId && (attType.equals("ID") || isXMLId(tName,q))) {
+// foundId = true;
+// xmlId = value;
+// }
+// if (!foundIdREFS && (attType.equals("IDREF") || isIDREF(tName,q))) {
+// foundIdREFS = true;
+// xmlIdREFS = new String[]{value};
+// }
+//
+// if (!foundIdREFS && (attType.equals("IDREFS") || isIDREFS(tName,q))) {
+// foundIdREFS = true;
+// xmlIdREFS = Utils.split(value," ", false);
+// }
+//
+//
+// boolean newOpened = checkOpenNsScopeAddNs(createdNSScope, q, value);
+// if (newOpened && !createdNSScope)
+// tok = new ElementToken(Type.START_TAG, tok.getNodeId(), tName, curNsScope);
+//
+// if (q.getNamespacePrefix() == null || q.getNamespacePrefix().equals("")) {
+// if (q.getLocalPart().equals("xmlns"))
+// continue;
+// } else if (q.getNamespacePrefix().equals("xmlns"))
+// continue;
+// NamedToken attToken = createAttributeToken(Type.UNTYPED_ATOMIC, value, q, curNsScope);
+// tokensList.add(attToken);
+//
+// if (foundId) {
+// NamedToken nmToken = (NamedToken) tok ;
+// nmToken.setID(xmlId);
+// }
+// if (foundIdREFS) {
+// NamedToken nmToken = (NamedToken) tok;
+// nmToken.setIDREFS(xmlIdREFS);
+// }
+//
+//
+// }
break;
default:
}
@@ -326,6 +469,20 @@
return Token.END_SEQUENCE_TOKEN;
}
+ private TokenInterface extractPendingElements(String name, String ns_uri,
+ String prefix) {
+ // we have reached the end of the path, and no subtree is needed: KEEP
+ // emit all the pending element nodes
+ for (int i=pathProducedLevel; i<bufferedPathName.size();i++) {
+ XQName tName = new QName(null, null, (String)bufferedPathName.elementAt(i));
+ tokensList.add(new ElementToken(Type.START_TAG, createNextTokenId(Type.START_TAG, tName.toString()), tName, curNsScope));
+ }
+ XQName tName = new QName(ns_uri, prefix, name);
+ tokensList.add(new ElementToken(Type.START_TAG, createNextTokenId(Type.START_TAG, tName.toString()), tName, curNsScope));
+ pathProducedLevel = level;
+ return (TokenInterface)tokensList.removeFirst();
+ }
+
public TokenInterface next() throws MXQueryException {
if (!tokensList.isEmpty()) {
TokenInterface tok = (TokenInterface) tokensList.removeFirst();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|