QSet<XsdElement::Ptr> collectAllElements(const XsdSchema::Ptr &schema)
{
    QSet<XsdElement::Ptr> elements;

    // collect global elements
    const XsdElement::List elementList = schema->elements();
    for (int i = 0; i < elementList.count(); ++i)
        elements.insert(elementList.at(i));

    // collect all elements from global groups
    const XsdModelGroup::List groupList = schema->elementGroups();
    for (int i = 0; i < groupList.count(); ++i) {
        const XsdModelGroup::Ptr group(groupList.at(i));

        for (int j = 0; j < group->particles().count(); ++j)
            elements.unite(collectAllElements(group->particles().at(j)));
    }

    // collect all elements from complex type definitions
    SchemaType::List types;
    types << schema->types() << schema->anonymousTypes();

    for (int i = 0; i < types.count(); ++i) {
        if (types.at(i)->isComplexType() && types.at(i)->isDefinedBySchema()) {
            const XsdComplexType::Ptr complexType(types.at(i));
            if (complexType->contentType()->particle())
                elements.unite(collectAllElements(complexType->contentType()->particle()));
        }
    }

    return elements;
}
Beispiel #2
0
/**
 * Internal helper method that checks if the given @p particle contains an element with the
 * same name and type twice.
 */
static bool hasDuplicatedElementsInternal(const XsdParticle::Ptr &particle, const NamePool::Ptr &namePool, ElementHash &hash, XsdElement::Ptr &conflictingElement)
{
    const XsdTerm::Ptr term = particle->term();
    if (term->isElement()) {
        const XsdElement::Ptr mainElement(term);
        XsdElement::List substGroups = mainElement->substitutionGroups();
        if (substGroups.isEmpty())
            substGroups << mainElement;

        for (int i = 0; i < substGroups.count(); ++i) {
            const XsdElement::Ptr element = substGroups.at(i);
            if (hash.contains(element->name(namePool))) {
                if (element->type()->name(namePool) != hash.value(element->name(namePool))->type()->name(namePool)) {
                    conflictingElement = element;
                    return true;
                }
            } else {
                hash.insert(element->name(namePool), element);
            }
        }
    } else if (term->isModelGroup()) {
        const XsdModelGroup::Ptr group(term);
        const XsdParticle::List particles = group->particles();
        for (int i = 0; i < particles.count(); ++i) {
            if (hasDuplicatedElementsInternal(particles.at(i), namePool, hash, conflictingElement))
                return true;
        }
    }

    return false;
}
void XsdSchemaDebugger::dumpSchema(const XsdSchema::Ptr &schema)
{
    qDebug() << "------------------------------ Schema -------------------------------";

    // elements
    {
        qDebug() << "Global Elements:";
        const XsdElement::List elements = schema->elements();
        for (int i = 0; i < elements.count(); ++i) {
            dumpElement(elements.at(i));
        }
    }

    // attributes
    {
        qDebug() << "Global Attributes:";
        const XsdAttribute::List attributes = schema->attributes();
        for (int i = 0; i < attributes.count(); ++i) {
            dumpAttribute(attributes.at(i));
        }
    }

    // types
    {
        qDebug() << "Global Types:";
        const SchemaType::List types = schema->types();
        for (int i = 0; i < types.count(); ++i) {
            dumpType(types.at(i));
        }
    }

    // anonymous types
    {
        qDebug() << "Anonymous Types:";
        const SchemaType::List types = schema->anonymousTypes();
        for (int i = 0; i < types.count(); ++i) {
            dumpType(types.at(i));
        }
    }

    qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
}
void XsdSchemaMerger::merge(const XsdSchema::Ptr &schema, const XsdSchema::Ptr &otherSchema)
{
    m_mergedSchema = XsdSchema::Ptr(new XsdSchema(otherSchema->namePool()));

    // first fill the merged schema with the values from schema
    if (schema) {
        const XsdElement::List elements = schema->elements();
        for (int i = 0; i < elements.count(); ++i) {
            m_mergedSchema->addElement(elements.at(i));
        }

        const XsdAttribute::List attributes = schema->attributes();
        for (int i = 0; i < attributes.count(); ++i) {
            m_mergedSchema->addAttribute(attributes.at(i));
        }

        const SchemaType::List types = schema->types();
        for (int i = 0; i < types.count(); ++i) {
            m_mergedSchema->addType(types.at(i));
        }

        const SchemaType::List anonymousTypes = schema->anonymousTypes();
        for (int i = 0; i < anonymousTypes.count(); ++i) {
            m_mergedSchema->addAnonymousType(anonymousTypes.at(i));
        }

        const XsdModelGroup::List elementGroups = schema->elementGroups();
        for (int i = 0; i < elementGroups.count(); ++i) {
            m_mergedSchema->addElementGroup(elementGroups.at(i));
        }

        const XsdAttributeGroup::List attributeGroups = schema->attributeGroups();
        for (int i = 0; i < attributeGroups.count(); ++i) {
            m_mergedSchema->addAttributeGroup(attributeGroups.at(i));
        }

        const XsdNotation::List notations = schema->notations();
        for (int i = 0; i < notations.count(); ++i) {
            m_mergedSchema->addNotation(notations.at(i));
        }

        const XsdIdentityConstraint::List identityConstraints = schema->identityConstraints();
        for (int i = 0; i < identityConstraints.count(); ++i) {
            m_mergedSchema->addIdentityConstraint(identityConstraints.at(i));
        }
    }

    // then merge in the values from the otherSchema
    {
        const XsdElement::List elements = otherSchema->elements();
        for (int i = 0; i < elements.count(); ++i) {
            if (!m_mergedSchema->element(elements.at(i)->name(otherSchema->namePool())))
                m_mergedSchema->addElement(elements.at(i));
        }

        const XsdAttribute::List attributes = otherSchema->attributes();
        for (int i = 0; i < attributes.count(); ++i) {
            if (!m_mergedSchema->attribute(attributes.at(i)->name(otherSchema->namePool())))
                m_mergedSchema->addAttribute(attributes.at(i));
        }

        const SchemaType::List types = otherSchema->types();
        for (int i = 0; i < types.count(); ++i) {
            if (!m_mergedSchema->type(types.at(i)->name(otherSchema->namePool())))
                m_mergedSchema->addType(types.at(i));
        }

        const SchemaType::List anonymousTypes = otherSchema->anonymousTypes();
        for (int i = 0; i < anonymousTypes.count(); ++i) {
            // add anonymous type as they are
            m_mergedSchema->addAnonymousType(anonymousTypes.at(i));
        }

        const XsdModelGroup::List elementGroups = otherSchema->elementGroups();
        for (int i = 0; i < elementGroups.count(); ++i) {
            if (!m_mergedSchema->elementGroup(elementGroups.at(i)->name(otherSchema->namePool())))
                m_mergedSchema->addElementGroup(elementGroups.at(i));
        }

        const XsdAttributeGroup::List attributeGroups = otherSchema->attributeGroups();
        for (int i = 0; i < attributeGroups.count(); ++i) {
            if (!m_mergedSchema->attributeGroup(attributeGroups.at(i)->name(otherSchema->namePool())))
                m_mergedSchema->addAttributeGroup(attributeGroups.at(i));
        }

        const XsdNotation::List notations = otherSchema->notations();
        for (int i = 0; i < notations.count(); ++i) {
            if (!m_mergedSchema->notation(notations.at(i)->name(otherSchema->namePool())))
                m_mergedSchema->addNotation(notations.at(i));
        }

        const XsdIdentityConstraint::List identityConstraints = otherSchema->identityConstraints();
        for (int i = 0; i < identityConstraints.count(); ++i) {
            if (!m_mergedSchema->identityConstraint(identityConstraints.at(i)->name(otherSchema->namePool())))
                m_mergedSchema->addIdentityConstraint(identityConstraints.at(i));
        }
    }
}
/*
 * Create the FSA according to Algorithm Tt(S) from http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html
 */
XsdStateMachine<XsdTerm::Ptr>::StateId XsdStateMachineBuilder::buildTerm(const XsdTerm::Ptr &term, XsdStateMachine<XsdTerm::Ptr>::StateId endState)
{
    if (term->isWildcard()) { // 1
        const XsdStateMachine<XsdTerm::Ptr>::StateId b = m_stateMachine->addState(XsdStateMachine<XsdTerm::Ptr>::InternalState);
        m_stateMachine->addTransition(b, term, endState);
        return b;
    } else if (term->isElement()) { // 2
        const XsdStateMachine<XsdTerm::Ptr>::StateId b = m_stateMachine->addState(XsdStateMachine<XsdTerm::Ptr>::InternalState);
        m_stateMachine->addTransition(b, term, endState);

        const XsdElement::Ptr element(term);
        if (m_mode == CheckingMode) {
            const XsdElement::List substGroups = element->substitutionGroups();
            for (int i = 0; i < substGroups.count(); ++i)
                m_stateMachine->addTransition(b, substGroups.at(i), endState);
        } else if (m_mode == ValidatingMode) {
            const XsdElement::List substGroups = element->substitutionGroups();
            for (int i = 0; i < substGroups.count(); ++i) {
                if (XsdSchemaHelper::substitutionGroupOkTransitive(element, substGroups.at(i), m_namePool))
                    m_stateMachine->addTransition(b, substGroups.at(i), endState);
            }
        }

        return b;
    } else if (term->isModelGroup()) {
        const XsdModelGroup::Ptr group(term);

        if (group->compositor() == XsdModelGroup::ChoiceCompositor) { // 3
            const XsdStateMachine<XsdTerm::Ptr>::StateId b = m_stateMachine->addState(XsdStateMachine<XsdTerm::Ptr>::InternalState);

            for (int i = 0; i < group->particles().count(); ++i) {
                const XsdParticle::Ptr particle(group->particles().at(i));
                if (particle->maximumOccurs() != 0) {
                    const XsdStateMachine<XsdTerm::Ptr>::StateId state = buildParticle(particle, endState);
                    m_stateMachine->addEpsilonTransition(b, state);
                }
            }

            return b;
        } else if (group->compositor() == XsdModelGroup::SequenceCompositor) { // 4
            XsdStateMachine<XsdTerm::Ptr>::StateId currentStartState = endState;
            XsdStateMachine<XsdTerm::Ptr>::StateId currentEndState = endState;

            for (int i = (group->particles().count() - 1); i >= 0; --i) { // iterate reverse
                const XsdParticle::Ptr particle(group->particles().at(i));
                if (particle->maximumOccurs() != 0) {
                    currentStartState = buildParticle(particle, currentEndState);
                    currentEndState = currentStartState;
                }
            }

            return currentStartState;
        } else if (group->compositor() == XsdModelGroup::AllCompositor) {
            const XsdStateMachine<XsdTerm::Ptr>::StateId newStartState = m_stateMachine->addState(XsdStateMachine<XsdTerm::Ptr>::InternalState);

            const QList<XsdParticle::List> list = allCombinations(group->particles());

            for (int i = 0; i < list.count(); ++i) {
                XsdStateMachine<XsdTerm::Ptr>::StateId currentStartState = endState;
                XsdStateMachine<XsdTerm::Ptr>::StateId currentEndState = endState;

                const XsdParticle::List particles = list.at(i);
                for (int j = (particles.count() - 1); j >= 0; --j) { // iterate reverse
                    const XsdParticle::Ptr particle(particles.at(j));
                    if (particle->maximumOccurs() != 0) {
                        currentStartState = buildParticle(particle, currentEndState);
                        currentEndState = currentStartState;
                    }
                }
                m_stateMachine->addEpsilonTransition(newStartState, currentStartState);
            }

            if (list.isEmpty())
                return endState;
            else
                return newStartState;
        }
    }

    Q_ASSERT(false);
    return 0;
}