示例#1
0
static void x2j_children( store::Item_t const &parent,
                          vector<store::Item_t> *children ) {
  ZORBA_ASSERT( children );
  store::Iterator_t i( parent->getChildren() );
  i->open();
  store::Item_t child_item, temp_item;
  while ( i->next( child_item ) ) {
    if ( !x2j_map_atomic( child_item, &temp_item ) ) {
      if ( !child_item->isNode() )
        throw XQUERY_EXCEPTION(
          zerr::ZJ2X0001_JSONML_ARRAY_BAD_JSON,
          ERROR_PARAMS( ZED( ZJ2X0001_BadElement ), child_item->getKind() )
        );
      switch ( child_item->getNodeKind() ) {
        case store::StoreConsts::elementNode:
          x2j_element( child_item, &temp_item );
          break;
        case store::StoreConsts::textNode: {
          zstring s( child_item->getStringValue() );
          GENV_ITEMFACTORY->createString( temp_item, s );
          break;
        }
        default:
          continue;
      } // switch
    } // if
    children->push_back( temp_item );
  } // while
  i->close();
}
void processOptions(store::Item_t item, store::LoadProperties& props, static_context* theSctx, const QueryLoc& loc)
{
  URI lValidatedBaseUri;
  store::Item_t child, tempItem;

  if (item.getp() == NULL)
    return;

#ifndef ZORBA_NO_XMLSCHEMA
  if (item->isValidated())
  {
    if (item->getNodeName() == NULL
        ||
        item->getNodeName()->getNamespace() != static_context::ZORBA_XML_FN_OPTIONS_NS)
    {
      throw XQUERY_EXCEPTION(zerr::ZXQD0003_INCONSISTENT_PARSE_FRAGMENT_OPTIONS,
                             ERROR_PARAMS(ZED(ParseFragmentInvalidOptions)), ERROR_LOC( loc ));
    }
  }
  else
  {
    tempItem = NULL; // used as the effectiveValidationValue()'s typeName
    Validator::effectiveValidationValue(
        item,
        item,
        tempItem,
        theSctx->get_typemanager(),
        ParseConstants::val_strict,
        theSctx,
        loc);
  }
#endif

  store::Iterator_t children = item->getChildren();
  children->open();

  while (children->next(child))
  {
    if (child->getNodeKind() != store::StoreConsts::elementNode)
      continue;

    if (child->getNodeName()->getLocalName() == "base-uri")
    {
      store::Item_t attr = getFirstAttribute(child);

      try {
        lValidatedBaseUri = URI(attr->getStringValue());
      } catch (ZorbaException const& /* e */) {
        throw XQUERY_EXCEPTION(
          err::FODC0007,
          ERROR_PARAMS( attr->getStringValue() ),
          ERROR_LOC( loc )
        );
      }

      if (!lValidatedBaseUri.is_absolute()) {
        throw XQUERY_EXCEPTION(
          err::FODC0007,
          ERROR_PARAMS( lValidatedBaseUri.toString() ),
          ERROR_LOC( loc )
        );
      }

      props.setBaseUri(attr->getStringValue());
    }
    else if (child->getNodeName()->getLocalName() == "no-error")
      props.setNoError(true);
    else if (child->getNodeName()->getLocalName() == "strip-boundary-space")
      props.setStripWhitespace(true);
    else if (child->getNodeName()->getLocalName() == "schema-validate")
    {
      store::Item_t attr = getFirstAttribute(child);
      if (attr->getStringValue() == "strict")
        props.setSchemaStrictValidate(true);
      else
        props.setSchemaLaxValidate(true);
    }
    else if (child->getNodeName()->getLocalName() == "DTD-validate")
      props.setDTDValidate(true);
    else if (child->getNodeName()->getLocalName() == "DTD-load")
      props.setDTDLoad(true);
    else if (child->getNodeName()->getLocalName() == "default-DTD-attributes")
      props.setDefaultDTDAttributes(true);
    else if (child->getNodeName()->getLocalName() == "parse-external-parsed-entity")
    {
      props.setParseExternalParsedEntity(true);
      store::Item_t attr;
      store::Iterator_t attribs = child->getAttributes();
      attribs->open();
      while (attribs->next(attr))
      {
        if (attr->getNodeName()->getLocalName() == "skip-root-nodes")
          props.setSkipRootNodes(ztd::aton<xs_int>(attr->getStringValue().c_str()));
        else if (attr->getNodeName()->getLocalName() == "skip-top-level-text-nodes")
          props.setSkipTopLevelTextNodes(true);
        else if (attr->getNodeName()->getLocalName() == "error-on-doctype")
          props.setErrorOnDoctype(true);
      }
      attribs->close();
    }
    else if (child->getNodeName()->getLocalName() == "substitute-entities")
      props.setSubstituteEntities(true);
    else if (child->getNodeName()->getLocalName() == "xinclude-substitutions")
      props.setXincludeSubstitutions(true);
    else if (child->getNodeName()->getLocalName() == "remove-redundant-ns")
      props.setRemoveRedundantNS(true);
    else if (child->getNodeName()->getLocalName() == "no-CDATA")
      props.setNoCDATA(true);
    else if (child->getNodeName()->getLocalName() == "no-xinclude-nodes")
      props.setNoXIncludeNodes(true);
    else if (child->getNodeName()->getLocalName() == "no-network-access")
      props.setNoNetworkAccess(true);
  }

  children->close();

  if (props.getSchemaLaxValidate() + props.getSchemaStrictValidate() +
      props.getDTDValidate() + props.getParseExternalParsedEntity() > 1)
  {
    throw XQUERY_EXCEPTION(zerr::ZXQD0003_INCONSISTENT_PARSE_FRAGMENT_OPTIONS,
                           ERROR_PARAMS(ZED(ParseFragmentOptionCombinationNotAllowed)), ERROR_LOC( loc ));
  }
}
示例#3
0
void SchemaValidatorImpl::processElement(
    store::PUL* pul,
    TypeManager* typeManager,
    EventSchemaValidator& schemaValidator,
    store::Item_t element,
    const QueryLoc& loc)
{
  ZORBA_ASSERT(element->isNode());
  ZORBA_ASSERT(element->getNodeKind() == store::StoreConsts::elementNode);

  store::Item_t nodeName = element->getNodeName();
  zstring baseUri;
  element->getBaseURI(baseUri);

  //cout << " vup    - processElement: " << nodeName->getLocalName()->c_str()
  //    << " @ " << nodeName->getNamespace()->c_str() << "\n"; cout.flush();

  schemaValidator.startElem(nodeName);

  // namespace declarations must go first
  processNamespaces( schemaValidator, element);

  // since the type of an element is determined only after the validator
  // receives all of it's attributes, and an attribute node needs it's
  // parent when created we need to go through the attributes twice: once
  // for validation and once for creation
  validateAttributes(schemaValidator, element->getAttributes());

  store::Item_t typeQName = schemaValidator.getTypeQName();
  store::Item_t substitutedElemQName = schemaValidator.getSubstitutedElemQName();

  //cout << " vup      - elemType old: "
  //    << element->getType()->getLocalName()->c_str() << " @ "
  //    << element->getType()->getNamespace()->c_str() << "\n"; cout.flush();
  //cout << " vup      - elemType new: " << typeQName->getLocalName()->c_str()
  //    << " @ " << typeQName->getNamespace()->c_str() << "\n"; cout.flush();

  bool isInSubstitutionElement = false;
  if (substitutedElemQName)
  {
    isInSubstitutionElement = true;
    //    cout << " vup        - substitutes: " << substitutedElemQName->g
    //  etLocalName()->c_str() << " @ " << substitutedElemQName->getNamespace()->
    // c_str() << "\n"; cout.flush();
  }

  bool isNewType = false;
  xqtref_t newType;
  store::Item_t elm;

  if ( !typeQName->equals(element->getType()) )
  {
    isNewType = true;
    newType = typeManager->create_named_type(typeQName, SequenceType::QUANT_ONE, loc);

    elm = element;
  }

  store::NsBindings bindings;
  element->getNamespaceBindings(bindings);
  namespace_context nsCtx = namespace_context(theSctx, bindings);

  processAttributes(pul, nsCtx, typeManager, schemaValidator, element, 
                    element->getAttributes(), loc);

  std::vector<store::Item_t> typedValues;
  int noOfChildren = processChildren(pul,
                                     nsCtx,
                                     typeManager, 
                                     schemaValidator,
                                     element->getChildren(),
                                     typedValues,
                                     loc);

  if ( isNewType )
  {
    bool tHasValue      = Validator::typeHasValue(newType);
    bool tHasTypedValue = Validator::typeHasTypedValue(typeManager, newType, loc);
    bool tHasEmptyValue = Validator::typeHasEmptyValue(newType);

    if ( noOfChildren==0 )
    {
      // workaround for elem of type xsd:string with no text child
      if ( newType->is_builtin() && 
          newType->getQName()->equals(GENV_TYPESYSTEM.STRING_TYPE_ONE->getQName()) )
      {
        /*store::Item_t result;
         zstring emptyStr = "";
         GENV_ITEMFACTORY->createString( result, emptyStr);
         typedValues.push_back(result);*/
        tHasEmptyValue = true;
        tHasTypedValue = false;
        tHasValue = false;
      }
      else if ( newType->type_kind()==XQType::USER_DEFINED_KIND )
      {
        const UserDefinedXQType udXQType = static_cast<const UserDefinedXQType&>(*newType);
        if ( udXQType.isSubTypeOf(typeManager, *GENV_TYPESYSTEM.STRING_TYPE_ONE) )
        {
          tHasEmptyValue = true;
          tHasTypedValue = false;
          tHasValue = false;
        }
      }
    }

    //cout << " vup        - addSetElementType: " << elm->getNodeName()->
    //  getLocalName()->str() << "   " << newType->get_qname()->getLocalName() 
    //  << " @ " << newType->get_qname()->getNamespace() << "\n"; cout.flush();
    //cout << " vup             - " << ( tHasTypedValue ? "hasTypedValue" : "" )
    //  << " values.size: " << typedValues.size() << (typedValues.size()>0 ? 
    // " [0]=" + typedValues[0]->getStringValue()->str() : "" ) << ( tHasValue ?
    // " hasValue" : "" ) << ( tHasEmptyValue ? " hasEmptyValue" : "" ) << "\n";
    //  cout.flush();

    if ( typedValues.size()==1 )
      pul->addSetElementType(&loc,
                             elm,
                             typeQName,
                             typedValues[0],
                             tHasValue,
                             tHasEmptyValue,
                             tHasTypedValue,
                             isInSubstitutionElement);
    else
      pul->addSetElementType(&loc,
                             elm,
                             typeQName,
                             (std::vector<store::Item_t>&)typedValues,
                             tHasValue,
                             tHasEmptyValue,
                             tHasTypedValue,
                             isInSubstitutionElement);
  }

  schemaValidator.endElem(nodeName);
}
bool FnZorbaParseXmlFragmentIterator::nextImpl(
    store::Item_t& result,
    PlanState& planState) const
{
  store::Store& lStore = GENV.getStore();
  zstring docString;
  store::Item_t tempItem;
  bool validated = true;

  FnZorbaParseXmlFragmentIteratorState* state;
  DEFAULT_STACK_INIT(FnZorbaParseXmlFragmentIteratorState, state, planState);

  if (consumeNext(result, theChildren[0].getp(), planState))
  {
    if (result->isStreamable())
    {
      state->theFragmentStream.theStream = &result->getStream();
      state->theFragmentStream.setStreamReleaser(result->getStreamReleaser());
      result->setStreamReleaser(nullptr);
    }
    else
    {
      result->getStringValue2(docString);
      state->theFragmentStream.theIss = new std::istringstream(docString.c_str());
      state->theFragmentStream.theStream = state->theFragmentStream.theIss;
    }

    // read options
    consumeNext(tempItem, theChildren[1].getp(), planState);
    state->theProperties.setBaseUri(theSctx->get_base_uri());
    state->theProperties.setStoreDocument(false);
    state->theProperties.setUseCachedDocument(false);
    processOptions(tempItem, state->theProperties, theSctx, loc);
    state->theProperties.setCreateDocParentLink(false);

    // baseURI serves both as the base URI used by the XML parser
    // to resolve relative entity references within the document,
    // and as the base URI of the document node that is returned.
    state->baseUri = state->theProperties.getBaseUri();
    state->docUri = state->theProperties.getBaseUri();


    ////////////////////////////////////////////////////////////////////////
    // External parsed entity processing
    ////////////////////////////////////////////////////////////////////////
    if (state->theProperties.getParseExternalParsedEntity())
    {
      state->theFragmentStream.root_elements_to_skip =
      state->theProperties.getSkipRootNodes();

      while ( ! state->theFragmentStream.stream_is_consumed())
      {
        try
        {
          result = lStore.loadDocument(state->baseUri,
                                       state->docUri,
                                       state->theFragmentStream,
                                       state->theProperties);
        }
        catch ( ZorbaException const &e )
        {
          if ( !state->theProperties.getNoError() )
          {
            XQueryException xe(
              XQUERY_EXCEPTION(
                err::FODC0006,
                ERROR_PARAMS( "parse-xml:parse()", e.what() ),
                ERROR_LOC( loc )
              )
            );
            set_data( xe, e );
            throw xe;
          }
          result = nullptr;
        }

        if (result == NULL)
          continue;

        // Return the children of document node
        state->theFragmentStream.children = result->getChildren();
        while (state->theFragmentStream.children->next(result) && result != NULL)
        {
          if (state->theProperties.getSkipTopLevelTextNodes() && result->getNodeKind() == store::StoreConsts::textNode)
            continue;

          STACK_PUSH(true, state);
        }
      }
    }
    ////////////////////////////////////////////////////////////////////////
    // XML document processing
    ////////////////////////////////////////////////////////////////////////
    else  // if (!state->theProperties.getEnableExtParsedEntity())
    {
      try 
      {
        result = lStore.loadDocument(state->baseUri, state->docUri, *state->theFragmentStream.theStream, state->theProperties);
      }
      catch ( ZorbaException const &e )
      {
        if ( !state->theProperties.getNoError() )
        {
          XQueryException xe(
            XQUERY_EXCEPTION(
              err::FODC0006,
              ERROR_PARAMS( "parse-xml:parse()", e.what() ),
              ERROR_LOC( loc )
            )
          );
          set_data( xe, e );
          throw xe;
        }
        result = nullptr;
      }

      if (result != NULL)
      {
#ifndef ZORBA_NO_XMLSCHEMA
        if (state->theProperties.getSchemaLaxValidate() ||
            state->theProperties.getSchemaStrictValidate())
        {
          try
          {
            tempItem = NULL; // used as the effectiveValidationValue()'s typeName
            validated = Validator::effectiveValidationValue(
                          result,
                          result,
                          tempItem,
                          theSctx->get_typemanager(),
                          state->theProperties.getSchemaLaxValidate() ? ParseConstants::val_lax : ParseConstants::val_strict,
                          theSctx,
                          this->loc);
          }
          catch (ZorbaException& /*e*/)
          {
            if ( ! state->theProperties.getNoError())
              throw;
            else
            {
              result = NULL;
              validated = false;
            }
          }
        }
#endif
        // Ignore the schema validation options if Zorba is built without schema support

        STACK_PUSH(validated, state);
      } // if (result != NULL)
    } // if (state->theProperties.getEnableExtParsedEntity())
  } // if (consumeNext(result, theChildren[0].getp(), planState))

  STACK_END(state);
}