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; }
/** * 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; }