Esempio n. 1
0
Item AttributeNameValidator::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    const Item name(m_operand->evaluateSingleton(context));
    const QXmlName qName(name.as<QNameValue>()->qName());

    if(qName.namespaceURI() == StandardNamespaces::xmlns)
    {
        context->error(QtXmlPatterns::tr("The namespace URI in the name for a "
                                         "computed attribute cannot be %1.")
                       .arg(formatURI(CommonNamespaces::XMLNS)),
                       ReportContext::XQDY0044, this);
        return Item(); /* Silence warning. */
    }
    else if(qName.namespaceURI() == StandardNamespaces::empty &&
            qName.localName() == StandardLocalNames::xmlns)
    {
        context->error(QtXmlPatterns::tr("The name for a computed attribute "
                                         "cannot have the namespace URI %1 "
                                         "with the local name %2.")
                          .arg(formatURI(CommonNamespaces::XMLNS))
                          .arg(formatKeyword("xmlns")),
                       ReportContext::XQDY0044, this);
        return Item(); /* Silence warning. */
    }
    else if(!qName.hasPrefix() && qName.hasNamespace())
    {
        return Item(QNameValue::fromValue(context->namePool(),
                                          QXmlName(qName.namespaceURI(), qName.localName(), StandardPrefixes::ns0)));
    }
    else
        return name;
}
void GenericNamespaceResolver::addBinding(const QXmlName nb)
{
    if(nb.namespaceURI() == StandardNamespaces::UndeclarePrefix)
        m_bindings.remove(nb.prefix());
    else
        m_bindings.insert(nb.prefix(), nb.namespaceURI());
}
Esempio n. 3
0
/**
 * This method is used by the isUPAConform method to check whether @p term and @p otherTerm
 * are the same resp. match each other.
 */
static bool termMatches(const XsdTerm::Ptr &term, const XsdTerm::Ptr &otherTerm, const NamePool::Ptr &namePool)
{
    if (term->isElement()) {
        const XsdElement::Ptr element(term);

        if (otherTerm->isElement()) {
            // both, the term and the other term are elements

            const XsdElement::Ptr otherElement(otherTerm);

            // if they have the same name they match
            if (element->name(namePool) == otherElement->name(namePool))
                return true;

        } else if (otherTerm->isWildcard()) {
            // the term is an element and the other term a wildcard

            const XsdWildcard::Ptr wildcard(otherTerm);

            // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
            QXmlName name = element->name(namePool);
            if (name.namespaceURI() == StandardNamespaces::empty)
                name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace()));

            // if the wildcards namespace constraint allows the elements name, they match
            if (XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, namePool))
                return true;
        }
    } else if (term->isWildcard()) {
        const XsdWildcard::Ptr wildcard(term);

        if (otherTerm->isElement()) {
            // the term is a wildcard and the other term an element

            const XsdElement::Ptr otherElement(otherTerm);

            // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
            QXmlName name = otherElement->name(namePool);
            if (name.namespaceURI() == StandardNamespaces::empty)
                name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace()));

            // if the wildcards namespace constraint allows the elements name, they match
            if (XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, namePool))
                return true;

        } else if (otherTerm->isWildcard()) {
            // both, the term and the other term are wildcards

            const XsdWildcard::Ptr otherWildcard(otherTerm);

            // check if the range of the wildcard overlaps.
            const XsdWildcard::Ptr intersectionWildcard = XsdSchemaHelper::wildcardIntersection(wildcard, otherWildcard);
            if (!intersectionWildcard ||
                (intersectionWildcard && !(intersectionWildcard->namespaceConstraint()->variety() != XsdWildcard::NamespaceConstraint::Not && intersectionWildcard->namespaceConstraint()->namespaces().isEmpty())))
                return true;
        }
    }

    return false;
}
void ComputedNamespaceConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
{
    const Item prefixItem(m_operand1->evaluateSingleton(context));
    const QString prefix(prefixItem ? prefixItem.stringValue() : QString());

    const Item namespaceItem(m_operand2->evaluateSingleton(context));
    const QString namespaceURI(namespaceItem ? namespaceItem.stringValue() : QString());

    if(namespaceURI.isEmpty())
    {
        context->error(QtXmlPatterns::tr("In a namespace constructor, the value for a namespace cannot be an empty string."),
                       ReportContext::XTDE0930,
                       this);
    }

    /* One optimization could be to store a pointer to
     * the name pool as a member in order to avoid the virtual call(s). */
    const NamePool::Ptr np(context->namePool());

    if(!prefix.isEmpty() && !QXmlUtils::isNCName(prefix))
    {
        context->error(QtXmlPatterns::tr("The prefix must be a valid %1, which %2 is not.")
                                        .arg(formatType(np, BuiltinTypes::xsNCName),
                                             formatKeyword(prefix)),
                       ReportContext::XTDE0920,
                       this);
    }
    const QXmlName binding(np->allocateBinding(prefix, namespaceURI));

    AnyURI::toQUrl<ReportContext::XTDE0905, DynamicContext::Ptr>(namespaceURI,
                                                                 context,
                                                                 this);

    if(binding.prefix() == StandardPrefixes::xmlns)
    {
        context->error(QtXmlPatterns::tr("The prefix %1 cannot be bound.")
                                        .arg(formatKeyword(prefix)),
                       ReportContext::XTDE0920,
                       this);
    }

    if((binding.prefix() == StandardPrefixes::xml && binding.namespaceURI() != StandardNamespaces::xml)
       ||
       (binding.prefix() != StandardPrefixes::xml && binding.namespaceURI() == StandardNamespaces::xml))
    {
        context->error(QtXmlPatterns::tr("Only the prefix %1 can be bound to %2 and vice versa.")
                                        .arg(formatKeyword(prefix), formatKeyword(namespaceURI)),
                       ReportContext::XTDE0925,
                       this);
    }

     context->outputReceiver()->namespaceBinding(binding);
}
FunctionSignature::Ptr XSLT10CoreFunctions::retrieveFunctionSignature(const NamePool::Ptr &np, const QXmlName name)
{
    if(StandardNamespaces::fn != name.namespaceURI())
        return FunctionSignature::Ptr();

    FunctionSignature::Ptr s(functionSignatures().value(name));

    if(!s)
    {
        /* Alphabetic order. */
        if(name.localName() == StandardLocalNames::function_available)
        {
            s = addFunction(StandardLocalNames::function_available, 1, 2, CommonSequenceTypes::ExactlyOneBoolean);
            s->appendArgument(argument(np, "function_name"), CommonSequenceTypes::ExactlyOneString);
            s->appendArgument(argument(np, "arity"), CommonSequenceTypes::ExactlyOneInteger);
        }
        else if(name.localName() == StandardLocalNames::system_property)
        {
            s = addFunction(StandardLocalNames::system_property, 1, 1, CommonSequenceTypes::ExactlyOneString);
            s->appendArgument(argument(np, "property_name"), CommonSequenceTypes::ExactlyOneString);
        }
    }

    return s;
}
Esempio n. 6
0
void AccelTreeBuilder<FromDocument>::startElement(const QXmlName &name, qint64 line, qint64 column)
{
    startStructure();

    AccelTree::BasicNodeData data(currentDepth(), currentParent(), QXmlNodeModelIndex::Element, -1, name);
    m_document->basicData.append(data);
    if (m_features & SourceLocationsFeature)
        m_document->sourcePositions.insert(m_document->maximumPreNumber(), qMakePair(line, column));

    ++m_preNumber;
    m_ancestors.push(m_preNumber);

    ++m_size.top();
    m_size.push(0);

    /* With node constructors, we can receive names for which we have no namespace
     * constructors, such as in the query '<xs:space/>'. Since the 'xs' prefix has no
     * NamespaceConstructor in this case, we synthesize the namespace.
     *
     * In case we're constructing from an XML document we avoid the call because
     * although it's redundant, it's on extra virtual call for each element. */
    if(!FromDocument)
        namespaceBinding(QXmlName(name.namespaceURI(), 0, name.prefix()));

    m_isPreviousAtomic = false;
}
QString ExternalEnvironment::retrieveProperty(const QXmlName name)
{
    if(name.namespaceURI() != StandardNamespaces::xslt)
        return QString();

    switch(name.localName())
    {
        case StandardLocalNames::version:
            return QString::number(ExternalEnvironment::XSLVersion);
        case StandardLocalNames::vendor:
            return ExternalEnvironment::Vendor;
        case StandardLocalNames::vendor_url:
            return QString(ExternalEnvironment::VendorURL.toString());
        case StandardLocalNames::product_name:
            return ExternalEnvironment::ProductName;
        case StandardLocalNames::product_version:
            return ExternalEnvironment::ProductVersion;
        case StandardLocalNames::is_schema_aware:
            return toString(ExternalEnvironment::IsSchemaAware);
        case StandardLocalNames::supports_serialization:
            return toString(ExternalEnvironment::SupportsSerialization);
        case StandardLocalNames::supports_backwards_compatibility:
            return toString(ExternalEnvironment::SupportsBackwardsCompatibility);
        default:
            return QString();
    }
}
QString SystemPropertyFN::retrieveProperty(const QXmlName name)
{
    if(name.namespaceURI() != StandardNamespaces::xslt)
        return QString();

    switch(name.localName())
    {
        case StandardLocalNames::version:
            /*
             * The supported XSL-T version.
             *
             * @see <a href="http://www.w3.org/TR/xslt20/#system-property">The Note paragraph
             * at the very end of XSL Transformations (XSLT) Version 2.0,
             * 16.6.5 system-property</a>
             */
            return QString::number(1.20);
        case StandardLocalNames::vendor:
            return QLatin1String("Digia Plc and/or its subsidiary(-ies), a Digia Company");
        case StandardLocalNames::vendor_url:
            return QLatin1String("http://qt.digia.com/");
        case StandardLocalNames::product_name:
            return QLatin1String("QtXmlPatterns");
        case StandardLocalNames::product_version:
            return QLatin1String("0.1");
        case StandardLocalNames::is_schema_aware:
        /* Fallthrough. */
        case StandardLocalNames::supports_backwards_compatibility:
        /* Fallthrough. */
        case StandardLocalNames::supports_serialization:
        /* Fallthrough. */
            return QLatin1String("no");
        default:
            return QString();
    }
}
Esempio n. 9
0
QString NamePool::displayName(const QXmlName qName) const
{
    QReadLocker l(mutableLock());

    if(qName.hasNamespace())
    {
        const QString &p = displayPrefix(qName.namespaceURI());

        if(p.isEmpty())
            return QLatin1Char('{') + m_namespaces.at(qName.namespaceURI()) + QLatin1Char('}') + toLexical(qName);
        else
            return p + QLatin1Char(':') + m_localNames.at(qName.localName());
    }
    else
        return m_localNames.at(qName.localName());
}
Esempio n. 10
0
void ReportContext::error(const QString &msg,
                          const QXmlName qname,
                          const SourceLocationReflection *const reflection)
{
    Q_ASSERT(!qname.isNull());
    createError(msg, QtFatalMsg,
                QUrl(namePool()->stringForNamespace(qname.namespaceURI()) + QLatin1Char('#') + namePool()->stringForLocalName(qname.localName())),
                lookupSourceLocation(reflection));
}
Esempio n. 11
0
QString NamePool::displayName(const QXmlName qName) const
{
    QReadLocker l(&lock);

    if(qName.hasNamespace())
    {
        if(qName.namespaceURI() == StandardNamespaces::InternalXSLT)
            return QLatin1Char('#') + m_localNames.at(qName.localName());

        const QString &p = displayPrefix(qName.namespaceURI());

        if(p.isEmpty())
            return QLatin1Char('{') + m_namespaces.at(qName.namespaceURI()) + QLatin1Char('}') + toLexical(qName);
        else
            return p + QLatin1Char(':') + m_localNames.at(qName.localName());
    }
    else
        return m_localNames.at(qName.localName());
}
Esempio n. 12
0
/*!
  \internal
 */
bool QXmlSerializer::isBindingInScope(const QXmlName nb) const
{
    Q_D(const QXmlSerializer);
    const int levelLen = d->namespaces.size();

    if(nb.prefix() == StandardPrefixes::empty)
    {
        for(int lvl = levelLen - 1; lvl >= 0; --lvl)
        {
            const QVector<QXmlName> &scope = d->namespaces.at(lvl);
            const int vectorLen = scope.size();

            for(int s = vectorLen - 1; s >= 0; --s)
            {
                const QXmlName &nsb = scope.at(s);

                if(nsb.prefix() == StandardPrefixes::empty)
                    return nsb.namespaceURI() == nb.namespaceURI();
            }
        }
    }
    else
    {
        for(int lvl = 0; lvl < levelLen; ++lvl)
        {
            const QVector<QXmlName> &scope = d->namespaces.at(lvl);
            const int vectorLen = scope.size();

            for(int s = 0; s < vectorLen; ++s)
            {
                const QXmlName &n = scope.at(s);
                if (n.prefix() == nb.prefix() &&
                    n.namespaceURI() == nb.namespaceURI())
                    return true;
            }
        }
    }

    return false;
}
Esempio n. 13
0
/*!
 \reimp
 */
void QXmlSerializer::namespaceBinding(const QXmlName &nb)
{
    /*
     * Writes out \a nb.
     *
     * Namespace bindings aren't looked up in a cache, because
     * we typically receive very few.
     */

    Q_D(QXmlSerializer);
    Q_ASSERT_X(!nb.isNull(), Q_FUNC_INFO,
               "It makes no sense to pass a null QXmlName.");

    Q_ASSERT_X((nb.namespaceURI() != StandardNamespaces::empty) ||
               (nb.prefix() == StandardPrefixes::empty),
               Q_FUNC_INFO,
               "Undeclarations of prefixes aren't allowed in XML 1.0 "
               "and aren't supposed to be received.");

    if(nb.namespaceURI() == QPatternist::StandardNamespaces::StopNamespaceInheritance)
        return;

    if(isBindingInScope(nb))
        return;

    d->namespaces.top().append(nb);

    if(nb.prefix() == StandardPrefixes::empty)
        write(" xmlns");
    else
    {
        write(" xmlns:");
        write(d->np->stringForPrefix(nb.prefix()));
    }

    write("=\"");
    writeEscapedAttribute(d->np->stringForNamespace(nb.namespaceURI()));
    d->write('"');
}
Esempio n. 14
0
Item NamespaceURIFN::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    const Item node(m_operands.first()->evaluateSingleton(context));

    if(node)
    {
        const QXmlName name(node.asNode().name());

        if(name.isNull())
            return CommonValues::EmptyAnyURI;
        else
            return toItem(AnyURI::fromValue(context->namePool()->stringForNamespace(name.namespaceURI())));
    }
    else
        return CommonValues::EmptyAnyURI;
}
Esempio n. 15
0
QString NamePool::toClarkName(const QXmlName &name) const
{
    if(name.isNull())
        return QLatin1String("QXmlName(null)");
    else
    {
        if(name.hasNamespace())
        {
            const QString ns(stringForNamespace(name.namespaceURI()));
            const QString p(stringForPrefix(name.prefix()));
            const QString l(stringForLocalName(name.localName()));

            return   QChar::fromLatin1('{')
                   + ns
                   + QChar::fromLatin1('}')
                   + (p.isEmpty() ? l : p + QChar::fromLatin1(':') + l);
        }
        else
            return stringForLocalName(name.localName());
    }
}
bool ElementAvailableFN::evaluateEBV(const DynamicContext::Ptr &context) const
{
    const Item arg(m_operands.first()->evaluateSingleton(context));
    const QString stringName(arg.stringValue());

    const QXmlName elementName(QNameConstructor::expandQName<DynamicContext::Ptr,
                                                             ReportContext::XTDE1440,
                                                             ReportContext::XTDE1440>(stringName,
                                                                                      context,
                                                                                      staticNamespaces(),
                                                                                      this,
                                                                                      false));

    if(elementName.namespaceURI() != StandardNamespaces::xslt)
        return false;

    QString prefix;
    QString localName;
    XPathHelper::splitQName(stringName, prefix, localName);

    return m_xsltInstructions.contains(localName);
}
QPatternist::SequenceType::Ptr
ExternalSourceLoader::announceExternalVariable(const QXmlName name,
                                               const QPatternist::SequenceType::Ptr &declaredType)
{
    pDebug() << "ExternalSourceLoader::announceExternalVariable()";
    Q_ASSERT(!name.isNull());
    Q_ASSERT(declaredType);
    Q_UNUSED(declaredType); /* Needed when bulding in release mode. */

    if(name.namespaceURI() == QPatternist::StandardNamespaces::empty)
    {
        const VariableValue variable(m_variableMap.value(Global::namePool()->stringForLocalName(name.localName())));

        if(variable.first.isEmpty())
            return QPatternist::SequenceType::Ptr();
        else
        {
            /* If announceDocument() can't load a document for uriForVar, it will return
             * null, which we will too, which is fine, since we can't supply a value for
             * this variable then. */
            if(variable.second == Document)
                return m_resourceLoader->announceDocument(variable.first, QPatternist::ResourceLoader::WillUse);
            else if(variable.second == URI)
            {
                return QPatternist::CommonSequenceTypes::ExactlyOneString;
            }
            else
            {
                /* The type is Query, and we don't pre-load
                 * them. No particular reason, just not worth it. */
                return QPatternist::CommonSequenceTypes::ZeroOrMoreItems;
            }
        }
    }
    else
        return QPatternist::SequenceType::Ptr();
}
FunctionSignature::Ptr XPath10CoreFunctions::retrieveFunctionSignature(const NamePool::Ptr &np, const QXmlName name)
{
    if(StandardNamespaces::fn != name.namespaceURI())
        return FunctionSignature::Ptr();

    FunctionSignature::Ptr s(functionSignatures().value(name));

    if(!s)
    {
        const QXmlName::LocalNameCode localName(name.localName());

        /* Alphabetic order. */
        if(StandardLocalNames::boolean == localName)
        {
            s = addFunction(StandardLocalNames::boolean, 1, 1, CommonSequenceTypes::ExactlyOneBoolean);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::EBV);
        }
        else if(StandardLocalNames::ceiling == localName)
        {
            s = addFunction(StandardLocalNames::ceiling, 1, 1, CommonSequenceTypes::ZeroOrOneNumeric,
                            Expression::EmptynessFollowsChild | Expression::RewriteToEmptyOnEmpty);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrOneNumeric);
        }
        else if(StandardLocalNames::concat == localName)
        {
            s = addFunction(StandardLocalNames::concat, 2, FunctionSignature::UnlimitedArity,
                            CommonSequenceTypes::ExactlyOneString);
            s->appendArgument(argument(np, "arg1"), CommonSequenceTypes::ZeroOrOneAtomicType);
            s->appendArgument(argument(np, "arg2"), CommonSequenceTypes::ZeroOrOneAtomicType);
        }
        else if(StandardLocalNames::contains == localName)
        {
            s = addFunction(StandardLocalNames::contains, 2, 3, CommonSequenceTypes::ExactlyOneBoolean,
                            Expression::LastOperandIsCollation);
            s->appendArgument(argument(np, "arg1"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "arg2"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "collation"), CommonSequenceTypes::ExactlyOneString);
        }
        else if(StandardLocalNames::count == localName)
        {
            s = addFunction(StandardLocalNames::count, 1, 1, CommonSequenceTypes::ExactlyOneInteger, Expression::IDCountFN);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrMoreItems);
        }
        else if(StandardLocalNames::False == localName)
        {
            s = addFunction(StandardLocalNames::False, 0, 0, CommonSequenceTypes::ExactlyOneBoolean);
        }
        else if(StandardLocalNames::floor == localName)
        {
            s = addFunction(StandardLocalNames::floor, 1, 1, CommonSequenceTypes::ZeroOrOneNumeric,
                            Expression::EmptynessFollowsChild | Expression::RewriteToEmptyOnEmpty);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrOneNumeric);
        }
        else if(StandardLocalNames::id == localName)
        {
            s = addFunction(StandardLocalNames::id, 1, 2, CommonSequenceTypes::ZeroOrMoreElements,
                            Expression::UseContextItem);
            s->appendArgument(argument(np, "idrefs"), CommonSequenceTypes::ZeroOrMoreStrings);
            s->appendArgument(argument(np, "node"), CommonSequenceTypes::ExactlyOneNode);
        }
        else if(StandardLocalNames::lang == localName)
        {
            s = addFunction(StandardLocalNames::lang, 1, 2, CommonSequenceTypes::ExactlyOneBoolean,
                            Expression::UseContextItem);
            s->appendArgument(argument(np, "testLang"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "node"), CommonSequenceTypes::ExactlyOneNode);
        }
        else if(StandardLocalNames::last == localName)
        {
            s = addFunction(StandardLocalNames::last, 0, 0, CommonSequenceTypes::ExactlyOneInteger,
                            Expression::DisableElimination | Expression::RequiresFocus);
        }
        else if(StandardLocalNames::local_name == localName)
        {
            s = addFunction(StandardLocalNames::local_name, 0, 1, CommonSequenceTypes::ExactlyOneString,
                            Expression::UseContextItem);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrOneNode);
        }
        else if(StandardLocalNames::name == localName)
        {
            s = addFunction(StandardLocalNames::name, 0, 1, CommonSequenceTypes::ExactlyOneString,
                            Expression::UseContextItem);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrOneNode);
        }
        else if(StandardLocalNames::namespace_uri == localName)
        {
            s = addFunction(StandardLocalNames::namespace_uri, 0, 1, CommonSequenceTypes::ExactlyOneAnyURI,
                            Expression::UseContextItem);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrOneNode);
        }
        else if(StandardLocalNames::normalize_space == localName)
        {
            s = addFunction(StandardLocalNames::normalize_space, 0, 1, CommonSequenceTypes::ExactlyOneString,
                            Expression::UseContextItem);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrOneString);
        }
        else if(StandardLocalNames::Not == localName)
        {
            s = addFunction(StandardLocalNames::Not, 1, 1, CommonSequenceTypes::ExactlyOneBoolean);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::EBV);
        }
        else if(StandardLocalNames::number == localName)
        {
            s = addFunction(StandardLocalNames::number, 0, 1, CommonSequenceTypes::ExactlyOneDouble,
                            Expression::UseContextItem);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrOneAtomicType);
        }
        else if(StandardLocalNames::position == localName)
        {
            s = addFunction(StandardLocalNames::position, 0, 0, CommonSequenceTypes::ExactlyOneInteger,
                            Expression::DisableElimination | Expression::RequiresFocus);
        }
        else if(StandardLocalNames::round == localName)
        {
            s = addFunction(StandardLocalNames::round, 1, 1, CommonSequenceTypes::ZeroOrOneNumeric,
                            Expression::EmptynessFollowsChild | Expression::RewriteToEmptyOnEmpty);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrOneNumeric);
        }
        else if(StandardLocalNames::starts_with == localName)
        {
            s = addFunction(StandardLocalNames::starts_with, 2, 3, CommonSequenceTypes::ExactlyOneBoolean,
                            Expression::LastOperandIsCollation);
            s->appendArgument(argument(np, "arg1"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "arg2"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "collation"), CommonSequenceTypes::ExactlyOneString);
        }
        else if(StandardLocalNames::string == localName)
        {
            s = addFunction(StandardLocalNames::string, 0, 1, CommonSequenceTypes::ExactlyOneString,
                            Expression::UseContextItem);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrOneItem);
        }
        else if(StandardLocalNames::string_length == localName)
        {
            s = addFunction(StandardLocalNames::string_length, 0, 1,
                            CommonSequenceTypes::ExactlyOneInteger,
                            Expression::UseContextItem);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrOneString);
        }
        else if(StandardLocalNames::substring == localName)
        {
            s = addFunction(StandardLocalNames::substring, 2, 3, CommonSequenceTypes::ExactlyOneString);
            s->appendArgument(argument(np, "sourceString"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "startingLoc"), CommonSequenceTypes::ExactlyOneDouble);
            s->appendArgument(argument(np, "length"), CommonSequenceTypes::ExactlyOneDouble);
        }
        else if(StandardLocalNames::substring_after == localName)
        {
            s = addFunction(StandardLocalNames::substring_after, 2, 3, CommonSequenceTypes::ExactlyOneString,
                            Expression::LastOperandIsCollation);
            s->appendArgument(argument(np, "arg1"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "arg2"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "collation"), CommonSequenceTypes::ExactlyOneString);
        }
        else if(StandardLocalNames::substring_before == localName)
        {
            s = addFunction(StandardLocalNames::substring_before, 2, 3, CommonSequenceTypes::ExactlyOneString,
                            Expression::LastOperandIsCollation);
            s->appendArgument(argument(np, "arg1"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "arg2"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "collation"), CommonSequenceTypes::ExactlyOneString);
        }
        else if(StandardLocalNames::sum == localName)
        {
            s = addFunction(StandardLocalNames::sum, 1, 2, CommonSequenceTypes::ZeroOrOneAtomicType);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrMoreAtomicTypes);
            s->appendArgument(argument(np, "zero"), CommonSequenceTypes::ZeroOrOneAtomicType);
        }
        else if(StandardLocalNames::translate == localName)
        {
            s = addFunction(StandardLocalNames::translate, 3, 3, CommonSequenceTypes::ExactlyOneString);
            s->appendArgument(argument(np, "arg"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "mapString"), CommonSequenceTypes::ExactlyOneString);
            s->appendArgument(argument(np, "transString"), CommonSequenceTypes::ExactlyOneString);
        }
        else if(StandardLocalNames::True == localName)
        {
            s = addFunction(StandardLocalNames::True, 0, 0, CommonSequenceTypes::ExactlyOneBoolean);
        }
    }

    return s;
}
Esempio n. 19
0
/**
 * This method is used by the subsumes algorithm to check whether the @p derivedTerm is validly derived from the @p baseTerm.
 *
 * @param baseTerm The term of the base component (type or group).
 * @param derivedTerm The term of the derived component (type or group).
 * @param particles A hash to map the passed base and derived term to the particles they belong to.
 * @param context The schema context.
 * @param errorMsg The error message in the case that an error occurs.
 */
static bool derivedTermValid(const XsdTerm::Ptr &baseTerm, const XsdTerm::Ptr &derivedTerm, const QHash<XsdTerm::Ptr, XsdParticle::Ptr> &particles, const XsdSchemaContext::Ptr &context, QString &errorMsg)
{
    const NamePool::Ptr namePool(context->namePool());

    // find the particles where the base and derived term belongs to
    const XsdParticle::Ptr baseParticle = particles.value(baseTerm);
    const XsdParticle::Ptr derivedParticle = particles.value(derivedTerm);

    // check that an empty particle can not be derived from a non-empty particle
    if (derivedParticle && baseParticle) {
        if (XsdSchemaHelper::isParticleEmptiable(derivedParticle) && !XsdSchemaHelper::isParticleEmptiable(baseParticle)) {
            errorMsg = QtXmlPatterns::tr("Empty particle cannot be derived from non-empty particle.");
            return false;
        }
    }

    if (baseTerm->isElement()) {
        const XsdElement::Ptr element(baseTerm);

        if (derivedTerm->isElement()) {
            // if both terms are elements

            const XsdElement::Ptr derivedElement(derivedTerm);

            // check names are equal
            if (element->name(namePool) != derivedElement->name(namePool)) {
                errorMsg = QtXmlPatterns::tr("Derived particle is missing element %1.").arg(formatKeyword(element->displayName(namePool)));
                return false;
            }

            // check value constraints are equal (if available)
            if (element->valueConstraint() && element->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) {
                if (!derivedElement->valueConstraint()) {
                    errorMsg = QtXmlPatterns::tr("Derived element %1 is missing value constraint as defined in base particle.").arg(formatKeyword(derivedElement->displayName(namePool)));
                    return false;
                }

                if (derivedElement->valueConstraint()->variety() != XsdElement::ValueConstraint::Fixed) {
                    errorMsg = QtXmlPatterns::tr("Derived element %1 has weaker value constraint than base particle.").arg(formatKeyword(derivedElement->displayName(namePool)));
                    return false;
                }

                const QSourceLocation dummyLocation(QUrl(QLatin1String("http://dummy.org")), 1, 1);
                const XsdTypeChecker checker(context, QVector<QXmlName>(), dummyLocation);
                if (!checker.valuesAreEqual(element->valueConstraint()->value(), derivedElement->valueConstraint()->value(), derivedElement->type())) {
                    errorMsg = QtXmlPatterns::tr("Fixed value constraint of element %1 differs from value constraint in base particle.").arg(formatKeyword(derivedElement->displayName(namePool)));
                    return false;
                }
            }

            // check that a derived element can not be nillable if the base element is not nillable
            if (!element->isNillable() && derivedElement->isNillable()) {
                errorMsg = QtXmlPatterns::tr("Derived element %1 cannot be nillable as base element is not nillable.").arg(formatKeyword(derivedElement->displayName(namePool)));
                return false;
            }

            // check that the constraints of the derived element are more strict then the constraints of the base element
            const XsdElement::BlockingConstraints baseConstraints = element->disallowedSubstitutions();
            const XsdElement::BlockingConstraints derivedConstraints = derivedElement->disallowedSubstitutions();
            if (((baseConstraints & XsdElement::RestrictionConstraint) && !(derivedConstraints & XsdElement::RestrictionConstraint)) ||
                ((baseConstraints & XsdElement::ExtensionConstraint) && !(derivedConstraints & XsdElement::ExtensionConstraint)) ||
                ((baseConstraints & XsdElement::SubstitutionConstraint) && !(derivedConstraints & XsdElement::SubstitutionConstraint))) {
                errorMsg = QtXmlPatterns::tr("Block constraints of derived element %1 must not be more weaker than in the base element.").arg(formatKeyword(derivedElement->displayName(namePool)));
                return false;
            }

            // if the type of both elements is the same we can stop testing here
            if (element->type()->name(namePool) == derivedElement->type()->name(namePool))
                return true;

            // check that the type of the derived element can validly derived from the type of the base element
            if (derivedElement->type()->isSimpleType()) {
                if (!XsdSchemaHelper::isSimpleDerivationOk(derivedElement->type(), element->type(), SchemaType::DerivationConstraints())) {
                    errorMsg = QtXmlPatterns::tr("Simple type of derived element %1 cannot be validly derived from base element.").arg(formatKeyword(derivedElement->displayName(namePool)));
                    return false;
                }
            } else if (derivedElement->type()->isComplexType()) {
                if (!XsdSchemaHelper::isComplexDerivationOk(derivedElement->type(), element->type(), SchemaType::DerivationConstraints())) {
                    errorMsg = QtXmlPatterns::tr("Complex type of derived element %1 cannot be validly derived from base element.").arg(formatKeyword(derivedElement->displayName(namePool)));
                    return false;
                }
            }

            // if both, derived and base element, have a complex type that contains a particle itself, apply the subsumes algorithm
            // recursive on their particles
            if (element->type()->isComplexType() && derivedElement->type()->isComplexType()) {
                if (element->type()->isDefinedBySchema() && derivedElement->type()->isDefinedBySchema()) {
                    const XsdComplexType::Ptr baseType(element->type());
                    const XsdComplexType::Ptr derivedType(derivedElement->type());
                    if ((baseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly ||
                        baseType->contentType()->variety() == XsdComplexType::ContentType::Mixed) &&
                        (derivedType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly ||
                         derivedType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) {

                        return XsdParticleChecker::subsumes(baseType->contentType()->particle(), derivedType->contentType()->particle(), context, errorMsg);
                    }
                }
            }

            return true;
        } else if (derivedTerm->isWildcard()) {
            // derive a wildcard from an element is not allowed
            errorMsg = QtXmlPatterns::tr("Element %1 is missing in derived particle.").arg(formatKeyword(element->displayName(namePool)));
            return false;
        }
    } else if (baseTerm->isWildcard()) {
        const XsdWildcard::Ptr wildcard(baseTerm);

        if (derivedTerm->isElement()) {
            // the base term is a wildcard and derived term an element

            const XsdElement::Ptr derivedElement(derivedTerm);

            // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
            QXmlName name = derivedElement->name(namePool);
            if (name.namespaceURI() == StandardNamespaces::empty)
                name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace()));

            // check that name of the element is allowed by the wildcards namespace constraint
            if (!XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, namePool)) {
                errorMsg = QtXmlPatterns::tr("Element %1 does not match namespace constraint of wildcard in base particle.").arg(formatKeyword(derivedElement->displayName(namePool)));
                return false;
            }

        } else if (derivedTerm->isWildcard()) {
            // both, derived and base term are wildcards

            const XsdWildcard::Ptr derivedWildcard(derivedTerm);

            // check that the derived wildcard is a valid subset of the base wildcard
            if (!XsdSchemaHelper::isWildcardSubset(derivedWildcard, wildcard)) {
                errorMsg = QtXmlPatterns::tr("Wildcard in derived particle is not a valid subset of wildcard in base particle.");
                return false;
            }

            if (!XsdSchemaHelper::checkWildcardProcessContents(wildcard, derivedWildcard)) {
                errorMsg = QtXmlPatterns::tr("processContent of wildcard in derived particle is weaker than wildcard in base particle.");
                return false;
            }
        }

        return true;
    }

    return false;
}
Esempio n. 20
0
void AccelTree::copyNodeTo(const QXmlNodeModelIndex &node,
                           QAbstractXmlReceiver *const receiver,
                           const NodeCopySettings &settings) const
{
    /* This code piece can be seen as a customized version of
     * QAbstractXmlReceiver::item/sendAsNode(). */
    Q_ASSERT(receiver);
    Q_ASSERT(!node.isNull());

    typedef QHash<QXmlName::PrefixCode, QXmlName::NamespaceCode> Binding;
    QStack<Binding> outputted;

    switch(node.kind())
    {
        case QXmlNodeModelIndex::Element:
        {
            outputted.push(Binding());

            /* Add the namespace for our element name. */
            const QXmlName elementName(node.name());

            receiver->startElement(elementName);

            if(!settings.testFlag(InheritNamespaces))
                receiver->namespaceBinding(QXmlName(StandardNamespaces::StopNamespaceInheritance, 0,
                                                    StandardPrefixes::StopNamespaceInheritance));

            if(settings.testFlag(PreserveNamespaces))
                node.sendNamespaces(receiver);
            else
            {
                /* Find the namespaces that we actually use and add them to outputted. These are drawn
                 * from the element name, and the node's attributes. */
                outputted.top().insert(elementName.prefix(), elementName.namespaceURI());

                const QXmlNodeModelIndex::Iterator::Ptr attributes(iterate(node, QXmlNodeModelIndex::AxisAttribute));
                QXmlNodeModelIndex attr(attributes->next());

                while(!attr.isNull())
                {
                    const QXmlName &attrName = attr.name();
                    outputted.top().insert(attrName.prefix(), attrName.namespaceURI());
                    attr = attributes->next();
                }

                Binding::const_iterator it(outputted.top().constBegin());
                const Binding::const_iterator end(outputted.top().constEnd());

                for(; it != end; ++it)
                    receiver->namespaceBinding(QXmlName(it.value(), 0, it.key()));
            }

            /* Send the attributes of the element. */
            {
                QXmlNodeModelIndex::Iterator::Ptr attributes(node.iterate(QXmlNodeModelIndex::AxisAttribute));
                QXmlNodeModelIndex attribute(attributes->next());

                while(!attribute.isNull())
                {
                    const QString &v = attribute.stringValue();
                    receiver->attribute(attribute.name(), QStringRef(&v));
                    attribute = attributes->next();
                }
            }

            /* Send the children of the element. */
            copyChildren(node, receiver, settings);

            receiver->endElement();
            outputted.pop();
            break;
        }
        case QXmlNodeModelIndex::Document:
        {
            /* We need to intercept and grab the elements of the document node, such
             * that we preserve/inherit preference applies to them. */
            receiver->startDocument();
            copyChildren(node, receiver, settings);
            receiver->endDocument();
            break;
        }
        default:
            receiver->item(node);
    }

}
Esempio n. 21
0
void AccelTreeBuilder<FromDocument>::attribute(const QXmlName &name, const QStringRef &value)
{
    /* Attributes adds a namespace binding, so lets synthesize one.
     *
     * We optimize by checking whether we have a namespace for which a binding would
     * be generated. Happens relatively rarely. */
    if(name.hasPrefix())
        namespaceBinding(QXmlName(name.namespaceURI(), 0, name.prefix()));

    m_document->basicData.append(AccelTree::BasicNodeData(currentDepth(), currentParent(), QXmlNodeModelIndex::Attribute, 0, name));
    ++m_preNumber;
    ++m_size.top();

    m_isPreviousAtomic = false;

    if(name.namespaceURI() == StandardNamespaces::xml && name.localName() == StandardLocalNames::id)
    {
        const QString normalized(value.toString().simplified());

        if(QXmlUtils::isNCName(normalized))
        {
            const QXmlName::LocalNameCode id = m_namePool->allocateLocalName(normalized);

            const int oldSize = m_document->m_IDs.count();
            m_document->m_IDs.insert(id, currentParent());
            /* We don't run the value through m_attributeCompress here, because
             * the likelyhood of it deing identical to another attribute is
             * very small. */
            m_document->data.insert(m_preNumber, normalized);

            /**
             * In the case that we're called for doc-available(), m_context is
             * null, and we need to flag somehow that we failed to load this
             * document.
             */
            if(oldSize == m_document->m_IDs.count() && m_context) // TODO
            {
                Q_ASSERT(m_context);
                m_context->error(QtXmlPatterns::tr("An %1-attribute with value %2 has already been declared.")
                                                   .arg(formatKeyword("xml:id"),
                                                        formatData(normalized)),
                                 FromDocument ? ReportContext::FODC0002 : ReportContext::XQDY0091,
                                 this);
            }
        }
        else if(m_context) // TODO
        {
            Q_ASSERT(m_context);

            /* If we're building from an XML Document(e.g, we're fed from QXmlStreamReader, we raise FODC0002,
             * otherwise XQDY0091. */
            m_context->error(QtXmlPatterns::tr("An %1-attribute must have a "
                                               "valid %2 as value, which %3 isn't.").arg(formatKeyword("xml:id"),
                                                                                         formatType(m_namePool, BuiltinTypes::xsNCName),
                                                                                         formatData(value.toString())),
                             FromDocument ? ReportContext::FODC0002 : ReportContext::XQDY0091,
                             this);
        }
    }
    else
        m_document->data.insert(m_preNumber, *m_attributeCompress.insert(value.toString()));
}
FunctionSignature::Ptr XSLT20CoreFunctions::retrieveFunctionSignature(const NamePool::Ptr &np, const QXmlName name)
{
    if(StandardNamespaces::fn != name.namespaceURI())
        return FunctionSignature::Ptr();

    FunctionSignature::Ptr s(functionSignatures().value(name));

    if(!s)
    {
        /* Alphabetic order. */
        if(name.localName() == StandardLocalNames::element_available)
        {
            s = addFunction(StandardLocalNames::element_available, 1, 1, CommonSequenceTypes::ExactlyOneBoolean);
            s->appendArgument(argument(np, "element-name"), CommonSequenceTypes::ExactlyOneString);
        }
        else if(name.localName() == StandardLocalNames::function_available)
        {
            s = addFunction(StandardLocalNames::function_available, 1, 2, CommonSequenceTypes::ExactlyOneBoolean);
            s->appendArgument(argument(np, "function_name"), CommonSequenceTypes::ExactlyOneString);
            s->appendArgument(argument(np, "arity"), CommonSequenceTypes::ExactlyOneInteger);
        }
        else if(name.localName() == StandardLocalNames::type_available)
        {
            s = addFunction(StandardLocalNames::type_available, 1, 1, CommonSequenceTypes::ExactlyOneBoolean);
            s->appendArgument(argument(np, "type_name"), CommonSequenceTypes::ExactlyOneString);
        }
        else if(name.localName() == StandardLocalNames::system_property)
        {
            s = addFunction(StandardLocalNames::system_property, 1, 1, CommonSequenceTypes::ExactlyOneString);
            s->appendArgument(argument(np, "property_name"), CommonSequenceTypes::ExactlyOneString);
        }
        else if(name.localName() == StandardLocalNames::generate_id)
        {
            s = addFunction(StandardLocalNames::generate_id, 0, 1, CommonSequenceTypes::ExactlyOneString,
                            Expression::UseContextItem);
            s->appendArgument(argument(np, "node"), CommonSequenceTypes::ZeroOrOneNode);
        }
        else if(name.localName() == StandardLocalNames::unparsed_text)
        {
            s = addFunction(StandardLocalNames::unparsed_text, 1, 2, CommonSequenceTypes::ZeroOrOneString,
                            Expression::DisableElimination);
            s->appendArgument(argument(np, "href"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "encoding"), CommonSequenceTypes::ExactlyOneString);
        }
        else if(name.localName() == StandardLocalNames::unparsed_text_available)
        {
            s = addFunction(StandardLocalNames::unparsed_text_available, 1, 2, CommonSequenceTypes::ExactlyOneBoolean,
                            Expression::DisableElimination);
            s->appendArgument(argument(np, "href"), CommonSequenceTypes::ZeroOrOneString);
            s->appendArgument(argument(np, "encoding"), CommonSequenceTypes::ZeroOrOneString);
        }
        else if(name.localName() == StandardLocalNames::current)
        {
            s = addFunction(StandardLocalNames::current, 0, 0, CommonSequenceTypes::ExactlyOneItem,
                            Expression::DisableElimination | Expression::RequiresCurrentItem);
        }
        else if(name.localName() == StandardLocalNames::document)
        {
            s = addFunction(StandardLocalNames::document, 1, 2, CommonSequenceTypes::OneOrMoreDocumentNodes,
                            Expression::DisableElimination);
            s->appendArgument(argument(np, "uri-sequence"), CommonSequenceTypes::ZeroOrMoreStrings);
            s->appendArgument(argument(np, "base-uri-node"), CommonSequenceTypes::ExactlyOneNode);
        }
        else if(name.localName() == StandardLocalNames::unparsed_entity_uri)
        {
            s = addFunction(StandardLocalNames::unparsed_entity_uri, 1, 1, CommonSequenceTypes::ExactlyOneAnyURI,
                            Expression::RequiresFocus | Expression::DisableElimination);
            s->appendArgument(argument(np, "entity-name"), CommonSequenceTypes::ExactlyOneString);
        }
        else if(name.localName() == StandardLocalNames::unparsed_entity_public_id)
        {
            s = addFunction(StandardLocalNames::unparsed_entity_public_id, 1, 1, CommonSequenceTypes::ExactlyOneString,
                            Expression::RequiresFocus | Expression::DisableElimination);
            s->appendArgument(argument(np, "entity-name"), CommonSequenceTypes::ExactlyOneString);
        }
    }

    return s;
}