/**
   * @param result
   * @param expr
   */
  private static void serialize(
      FastStringBuffer result, Expression expr, Map reversePrefixMapping) {
    if (expr instanceof Assignation) {
      // XXX not yet supported
    } else if (expr instanceof AxisExpression) {
      AxisExpression axisExpression = (AxisExpression) expr;
      result.append(Axis.axisName[axisExpression.getAxis()]);
      result.append("::");

      final NodeTest nodeTest = axisExpression.getNodeTest();
      if (nodeTest == null) {
        result.append("node()");
      } else {
        result.append(fixPreFixes(nodeTest.toString(), reversePrefixMapping));
      }
    } else if (expr instanceof BinaryExpression) {
      BinaryExpression binaryExpression = (BinaryExpression) expr;
      result.append('(');
      serialize(result, binaryExpression.getOperands()[0], reversePrefixMapping);
      result.append(Token.tokens[binaryExpression.getOperator()]);
      serialize(result, binaryExpression.getOperands()[1], reversePrefixMapping);
      result.append(')');
    } else if (expr instanceof CompareToIntegerConstant) {
      CompareToIntegerConstant compareToIntegerConstant = (CompareToIntegerConstant) expr;
      result.append('(');
      serialize(result, compareToIntegerConstant.getOperand(), reversePrefixMapping);
      result.append(Token.tokens[compareToIntegerConstant.getComparisonOperator()]);
      result.append(Long.toString(compareToIntegerConstant.getComparand()));
      result.append(')');
    } else if (expr instanceof ConditionalSorter) {
      // XXX not yet supported
    } else if (expr instanceof ContextItemExpression) {
      result.append('.');
    } else if (expr instanceof ErrorExpression) {
      // Error do nothing
    } else if (expr instanceof FilterExpression) {
      FilterExpression filterExpression = (FilterExpression) expr;
      result.append('(');
      serialize(result, filterExpression.getControllingExpression(), reversePrefixMapping);
      result.append('[');
      serialize(result, filterExpression.getFilter(), reversePrefixMapping);
      result.append("])");

    } else if (expr instanceof FunctionCall) {
      FunctionCall functionCall = (FunctionCall) expr;
      StructuredQName name = functionCall.getFunctionName();
      if (name.getPrefix() != null && name.getPrefix().length() > 0) {
        result.append(name.getPrefix());
        result.append(":");
      }
      result.append(name.getLocalName());
      result.append("(");

      Iterator iter = functionCall.iterateSubExpressions();
      boolean first = true;
      while (iter.hasNext()) {
        result.append(first ? "" : ", ");
        SaxonXPathExpressionSerializer.serialize(
            result, (Expression) iter.next(), reversePrefixMapping);
        first = false;
      }

      result.append(")");
    } else if (expr instanceof Instruction) {
      // This is not an XPath expression
    } else if (expr instanceof IntegerRangeTest) {
      // XXX not yet supported
    } else if (expr instanceof IsLastExpression) {
      result.append("position() eq last()");
    } else if (expr instanceof Literal) {
      Literal literal = (Literal) expr;
      result.append(literal.getValue().toString());
    } else if (expr instanceof NumberInstruction) {
      // This is not an XPath expression
    } else if (expr instanceof PathExpression) {
      PathExpression pathExpression = (PathExpression) expr;
      result.append('(');
      serialize(result, pathExpression.getControllingExpression(), reversePrefixMapping);
      result.append('/');
      serialize(result, pathExpression.getControlledExpression(), reversePrefixMapping);
      result.append(')');
    } else if (expr instanceof PatternMatchExpression) {
      // XXX not yet supported
    } else if (expr instanceof PatternSponsor) {
      // XXX not yet supported
    } else if (expr instanceof SimpleContentConstructor) {
      // This is not an XPath expression
    } else if (expr instanceof SimpleExpression) {
      // This is not an XPath expression
    }
    /*
        else if (expr instanceof SimpleMappingExpression) {
    	    // XXX not yet supported
    	}
    */
    else if (expr instanceof ParentNodeExpression) {
      result.append("..");
    } else if (expr instanceof RootExpression) {
      // do nothing
    } else if (expr instanceof SortExpression) {
      // XXX not yet supported
    } else if (expr instanceof TailExpression) {
      // XXX not yet supported
    } else if (expr instanceof TupleExpression) {
      // This is not an XPath expression
    } else if (expr instanceof TupleSorter) {
      // This is not an XPath expression
    } else if (expr instanceof UnaryExpression) {
      UnaryExpression unaryExpression = (UnaryExpression) expr;
      serialize(
          result,
          unaryExpression.getBaseExpression(),
          reversePrefixMapping); // Not sure if this is correct in all cases
    } else if (expr instanceof VariableReference) {
      VariableReference variableReference = (VariableReference) expr;
      String d = variableReference.getDisplayName();
      result.append("$");
      result.append(d == null ? "$" : d);
    }
  }
예제 #2
0
  /** Type-check the expression */
  public Expression typeCheck(ExpressionVisitor visitor, ItemType contextItemType)
      throws XPathException {

    Configuration config = visitor.getConfiguration();
    NamePool namePool = config.getNamePool();
    StaticContext env = visitor.getStaticContext();
    if (contextItemType == null) {
      typeError(
          visitor,
          "Axis step " + toString(namePool) + " cannot be used here: the context item is undefined",
          "XPDY0002",
          null);
    }
    if (contextItemType.isAtomicType()) {
      typeError(
          visitor,
          "Axis step "
              + toString(namePool)
              + " cannot be used here: the context item is an atomic value",
          "XPTY0020",
          null);
    }

    if (this.contextItemType == contextItemType && doneWarnings) {
      return this;
    }

    this.contextItemType = contextItemType;
    doneWarnings = true;

    if (contextItemType instanceof NodeTest) {
      int origin = contextItemType.getPrimitiveType();
      if (origin != Type.NODE) {
        if (Axis.isAlwaysEmpty(axis, origin)) {
          env.issueWarning(
              "The "
                  + Axis.axisName[axis]
                  + " axis starting at "
                  + (origin == Type.ELEMENT || origin == Type.ATTRIBUTE ? "an " : "a ")
                  + NodeKindTest.nodeKindName(origin)
                  + " node will never select anything",
              getSourceLocator());
          return Literal.makeEmptySequence();
        }
      }

      if (test != null) {
        int kind = test.getPrimitiveType();
        if (kind != Type.NODE) {
          if (!Axis.containsNodeKind(axis, kind)) {
            env.issueWarning(
                "The "
                    + Axis.axisName[axis]
                    + " axis will never select any "
                    + NodeKindTest.nodeKindName(kind)
                    + " nodes",
                getSourceLocator());
            return Literal.makeEmptySequence();
          }
        }
        if (axis == Axis.SELF && kind != Type.NODE && origin != Type.NODE && kind != origin) {
          env.issueWarning(
              "The self axis will never select any "
                  + NodeKindTest.nodeKindName(kind)
                  + " nodes when starting at "
                  + (origin == Type.ELEMENT || origin == Type.ATTRIBUTE ? "an " : "a ")
                  + NodeKindTest.nodeKindName(origin)
                  + " node",
              getSourceLocator());
          return Literal.makeEmptySequence();
        }
        if (axis == Axis.SELF) {
          itemType = new CombinedNodeTest(test, Token.INTERSECT, (NodeTest) contextItemType);
        }

        // If the content type of the context item is known, see whether the node test can select
        // anything

        if (contextItemType instanceof DocumentNodeTest && kind == Type.ELEMENT) {
          NodeTest elementTest = ((DocumentNodeTest) contextItemType).getElementTest();
          Set<Integer> outermostElementNames = elementTest.getRequiredNodeNames();
          if (outermostElementNames != null) {
            Set<Integer> selectedElementNames = test.getRequiredNodeNames();
            if (selectedElementNames != null) {
              if (axis == Axis.CHILD) {
                // check that the name appearing in the step is one of the names allowed by the
                // nodetest

                if (SetUtils.intersect(selectedElementNames, outermostElementNames).isEmpty()) {
                  env.issueWarning(
                      "Starting at a document node, the step is selecting an element whose name "
                          + "is not among the names of child elements permitted for this document node type",
                      getSourceLocator());

                  return Literal.makeEmptySequence();
                }
                itemType = elementTest;
                return this;

              } else if (axis == Axis.DESCENDANT) {
                // check that the name appearing in the step is one of the names allowed by the
                // nodetest
                boolean canMatchOutermost =
                    !SetUtils.intersect(selectedElementNames, outermostElementNames).isEmpty();
                if (!canMatchOutermost) {
                  // The expression /descendant::x starting at the document node doesn't match the
                  // outermost
                  // element, so replace it by child::*/descendant::x, and check that
                  PathExpression path =
                      new PathExpression(
                          new AxisExpression(Axis.CHILD, elementTest),
                          new AxisExpression(Axis.DESCENDANT, test));
                  ExpressionTool.copyLocationInfo(this, path);
                  return path.typeCheck(visitor, contextItemType);
                }
              }
            }
          }
        }
      }
    }

    return this;
  }