Exemple #1
0
 def stepAxis(self, op, p, sourceSequence):
     targetSequence = []
     for node in sourceSequence:
         if not isinstance(node,(ModelObject, etree._ElementTree, ModelAttribute)):
             raise XPathException(self.progHeader, 'err:XPTY0020', _('Axis step {0} context item is not a node: {1}').format(op, node))
         targetNodes = []
         if isinstance(p,QNameDef):
             ns = p.namespaceURI; localname = p.localName
             if p.isAttribute:
                 if isinstance(node,ModelObject):
                     attrTag = p.localName if p.unprefixed else p.clarkNotation
                     modelAttribute = None
                     try:
                         modelAttribute = node.xAttributes[attrTag]
                     except (AttributeError, TypeError, IndexError, KeyError):
                         # may be lax or deferred validated
                         try:
                             validate(node.modelXbrl, node, p)
                             modelAttribute = node.xAttributes[attrTag]
                         except (AttributeError, TypeError, IndexError, KeyError):
                             pass
                     if modelAttribute is None:
                         value = node.get(attrTag)
                         if value is not None:
                             targetNodes.append(ModelAttribute(node,p.clarkNotation,UNKNOWN,value,value,value))
                     elif modelAttribute.xValid >= VALID:
                             targetNodes.append(modelAttribute)
             elif op == '/' or op is None:
                 if isinstance(node,(ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.children(node, ns, localname)
             elif op == '//':
                 if isinstance(node,(ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.descendants(node, ns, localname)
             elif op == '..':
                 if isinstance(node,ModelAttribute):
                     targetNodes = [ node.modelElement ]
                 else:
                     targetNodes = [ XmlUtil.parent(node) ]
         elif isinstance(p, OperationDef) and isinstance(p.name,QNameDef):
             if isinstance(node,ModelObject):
                 if p.name.localName == "text":
                     targetNodes = [XmlUtil.text(node)]
                 # todo: add element, attribute, node, etc...
         elif p == '*':  # wildcard
             if op == '/' or op is None:
                 if isinstance(node,(ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.children(node, '*', '*')
             elif op == '//':
                 if isinstance(node,(ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.descendants(node, '*', '*')
         targetSequence.extend(targetNodes)
     return targetSequence
Exemple #2
0
def element_attribute(element, attrQname):
    attrTag = attrQname.clarkNotation
    modelAttribute = None
    try:
        modelAttribute = element.xAttributes[attrTag]
    except (AttributeError, TypeError, IndexError, KeyError):
        # may be lax or deferred validated
        try:
            validate(element.modelXbrl, element, attrQname)
            modelAttribute = element.xAttributes[attrTag]
        except (AttributeError, TypeError, IndexError, KeyError):
            pass
    if modelAttribute is None:
        value = element.get(attrTag)
        if value is not None:
            return value
    elif modelAttribute.xValid >= VALID:
        return modelAttribute.xValue
    return ()
def validateElementSequence(modelXbrl, compositor, children, ixFacts, iNextChild=0):
    particles = compositor.dereference().particles        
    iStartingChild = iNextChild
    errDesc = None
    if isinstance(compositor, ModelAll):
        allParticles = set() # elements required
        iNextAfterAll = iStartingChild
    elif isinstance(compositor, ModelChoice):
        anyChoiceHasMinOccurs0 = False
    moreParticlesPasses = True
    while moreParticlesPasses:
        moreParticlesPasses = False
        for particle in particles:
            occurences = 0
            if isinstance(particle, (ModelConcept, ModelAny)):
                elementDeclaration = particle.dereference()
                while iNextChild < len(children):
                    elt = children[iNextChild]
                    vQname = elt.vQname(modelXbrl) # takes care of elements inside inline or other instances
                    if isinstance(elt, ModelObject):
                        # for any, check namespace overlap
                        if ((isinstance(particle, ModelAny) and 
                             particle.allowsNamespace(vQname.namespaceURI)) or 
                            (isinstance(particle, ModelConcept) and
                             elementDeclaration is not None and 
                             (vQname == elementDeclaration.qname or 
                              elt.elementDeclaration(modelXbrl).substitutesForQname(elementDeclaration.qname)))):
                            occurences += 1
                            validate(modelXbrl, elt, ixFacts=ixFacts)
                            iNextChild += 1
                            if occurences == particle.maxOccurs:
                                break
                        elif not isinstance(particle, ModelAll):
                            break # done with this element
                    else: # comment or processing instruction, skip over it
                        iNextChild += 1
            else:  # group definition or compositor
                while occurences < particle.maxOccurs:
                    iPrevChild = iNextChild
                    iNextChild, occured, errDesc, errArgs = validateElementSequence(modelXbrl, particle, children, ixFacts, iNextChild)
                    if occured:
                        # test if occurence was because of minOccurs zero but no match occured (HF 2012-09-07)
                        if occured and iNextChild == iPrevChild and particle.minOccurs == 0: # nothing really occured
                            break
                        occurences += 1
                        if occurences == particle.maxOccurs or iNextChild >= len(children):
                            break
                    else:
                        break
            if isinstance(compositor, ModelChoice):
                if occurences > 0 and particle.minOccurs <= occurences <= particle.maxOccurs:
                    return (iNextChild, True, None, None)  # choice has been selected
                else: # otherwise start again on next choice
                    if particle.minOccurs == 0:
                        anyChoiceHasMinOccurs0 = True
                    iNextChild = iStartingChild
            elif isinstance(compositor, ModelAll):
                if particle.minOccurs <= occurences <= particle.maxOccurs:
                    allParticles.add(particle)  # particle found
                    moreParticlesPasses = True
                    break # advance to next all particle
            elif particle.minOccurs > 0 and errDesc:
                return (iNextChild, False, errDesc, errArgs)
            elif not particle.minOccurs <= occurences <= particle.maxOccurs:
                return (iNextChild, False,
                        ("xmlSchema:elementOccurencesError", 
                         _("%(compositor)s(%(particles)s) %(element)s occured %(occurences)s times, minOccurs=%(minOccurs)s, maxOccurs=%(maxOccurs)s, within %(parentElement)s")),
                        dict(compositor=compositor, particles=particles, occurences=occurences, minOccurs=particle.minOccursStr, maxOccurs=particle.maxOccursStr))
    if isinstance(compositor, ModelAll):
        missingParticles = set(particles) - allParticles
        if missingParticles:
            return (iNextChild, False,
                    ("xmlSchema:missingParticlesError",
                     _("All(%(particles)s) missing at %(element)s, within %(parentElement)s")),
                    dict(particles=particles))
        occured = True
    elif isinstance(compositor, ModelChoice):
        occured = anyChoiceHasMinOccurs0 # deemed to have occured if any choice had minoccurs=0
    else:
        occured = True
    if isinstance(compositor, ModelType) and iNextChild < len(children):
        #elt = children[iNextChild]
        #eltChildren = elt.modelTupleFacts if ixFacts else elt
        #if any(True for child in eltChildren if isinstance(child, ModelObject)): # any unexpected content elements
        if any(True for child in children[iNextChild:] if isinstance(child, ModelObject)): # any unexpected content elements
            return (iNextChild, False,
                    ("xmlSchema:elementUnexpected",
                     _("%(compositor)s(%(particles)s) %(element)s unexpected, within %(parentElement)s")),
                    dict(compositor=compositor, particles=particles))
    return (iNextChild, occured, None, None)
Exemple #4
0
 def stepAxis(self, op, p, sourceSequence):
     targetSequence = []
     for node in sourceSequence:
         if not isinstance(
                 node, (ModelObject, etree._ElementTree, ModelAttribute)):
             raise XPathException(
                 self.progHeader, 'err:XPTY0020',
                 _('Axis step {0} context item is not a node: {1}').format(
                     op, node))
         targetNodes = []
         if isinstance(p, QNameDef):
             ns = p.namespaceURI
             localname = p.localName
             axis = p.axis
             if p.isAttribute:
                 if isinstance(node, ModelObject):
                     attrTag = p.localName if p.unprefixed else p.clarkNotation
                     modelAttribute = None
                     try:
                         modelAttribute = node.xAttributes[attrTag]
                     except (AttributeError, TypeError, IndexError,
                             KeyError):
                         # may be lax or deferred validated
                         try:
                             validate(node.modelXbrl, node, p)
                             modelAttribute = node.xAttributes[attrTag]
                         except (AttributeError, TypeError, IndexError,
                                 KeyError):
                             pass
                     if modelAttribute is None:
                         value = node.get(attrTag)
                         if value is not None:
                             targetNodes.append(
                                 ModelAttribute(node, p.clarkNotation,
                                                UNKNOWN, value, value,
                                                value))
                     elif modelAttribute.xValid >= VALID:
                         targetNodes.append(modelAttribute)
             elif op == '/' or op is None:
                 if axis is None or axis == "child":
                     if isinstance(node, (ModelObject, etree._ElementTree)):
                         targetNodes = XmlUtil.children(node, ns, localname)
                 elif axis == "parent":
                     if isinstance(node, ModelAttribute):
                         parentNode = [node.modelElement]
                     else:
                         parentNode = [XmlUtil.parent(node)]
                     if (isinstance(node, ModelObject)
                             and (not ns or ns == parentNode.namespaceURI
                                  or ns == "*")
                             and (localname == parentNode.localName
                                  or localname == "*")):
                         targetNodes = [parentNode]
                 elif axis == "self":
                     if (isinstance(node, ModelObject) and
                         (not ns or ns == node.namespaceURI or ns == "*")
                             and
                         (localname == node.localName or localname == "*")):
                         targetNodes = [node]
                 elif axis.startswith("descendant"):
                     if isinstance(node, (ModelObject, etree._ElementTree)):
                         targetNodes = XmlUtil.descendants(
                             node, ns, localname)
                         if (axis.endswith("-or-self")
                                 and isinstance(node, ModelObject)
                                 and (not ns or ns == node.namespaceURI
                                      or ns == "*")
                                 and (localname == node.localName
                                      or localname == "*")):
                             targetNodes.append(node)
                 elif axis.startswith("ancestor"):
                     if isinstance(node, ModelObject):
                         targetNodes = [
                             ancestor
                             for ancestor in XmlUtil.ancestors(node)
                             if ((not ns or ns == ancestor.namespaceURI
                                  or ns == "*") and (
                                      localname == ancestor.localName
                                      or localname == "*"))
                         ]
                         if (axis.endswith("-or-self")
                                 and isinstance(node, ModelObject)
                                 and (not ns or ns == node.namespaceURI
                                      or ns == "*")
                                 and (localname == node.localName
                                      or localname == "*")):
                             targetNodes.insert(0, node)
                 elif axis.endswith("-sibling"):
                     if isinstance(node, ModelObject):
                         targetNodes = [
                             sibling for sibling in node.itersiblings(
                                 preceding=axis.startswith("preceding"))
                             if ((not ns or ns == sibling.namespaceURI
                                  or ns == "*") and (
                                      localname == sibling.localName
                                      or localname == "*"))
                         ]
                 elif axis == "preceding":
                     if isinstance(node, ModelObject):
                         for preceding in node.getroottree().iter():
                             if preceding == node:
                                 break
                             elif ((not ns or ns == preceding.namespaceURI
                                    or ns == "*")
                                   and (localname == preceding.localName
                                        or localname == "*")):
                                 targetNodes.append(preceding)
                 elif axis == "following":
                     if isinstance(node, ModelObject):
                         foundNode = False
                         for following in node.getroottree().iter():
                             if following == node:
                                 foundNode = True
                             elif (foundNode and
                                   (not ns or ns == following.namespaceURI
                                    or ns == "*")
                                   and (localname == following.localName
                                        or localname == "*")):
                                 targetNodes.append(following)
             elif op == '//':
                 if isinstance(node, (ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.descendants(node, ns, localname)
             elif op == '..':
                 if isinstance(node, ModelAttribute):
                     targetNodes = [node.modelElement]
                 else:
                     targetNodes = [XmlUtil.parent(node)]
         elif isinstance(p, OperationDef) and isinstance(p.name, QNameDef):
             if isinstance(node, ModelObject):
                 if p.name.localName == "text":  # note this is not string value, just child text
                     targetNodes = [node.textValue]
                 # todo: add element, attribute, node, etc...
         elif p == '*':  # wildcard
             if op == '/' or op is None:
                 if isinstance(node, (ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.children(node, '*', '*')
             elif op == '//':
                 if isinstance(node, (ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.descendants(node, '*', '*')
         targetSequence.extend(targetNodes)
     return targetSequence
Exemple #5
0
def validateElementSequence(modelXbrl, compositor, children, ixFacts, iNextChild=0):
    particles = compositor.dereference().particles        
    iStartingChild = iNextChild
    errDesc = None
    if isinstance(compositor, ModelAll):
        allParticles = set() # elements required
        iNextAfterAll = iStartingChild
    elif isinstance(compositor, ModelChoice):
        anyChoiceHasMinOccurs0 = False
    moreParticlesPasses = True
    while moreParticlesPasses:
        moreParticlesPasses = False
        for particle in particles:
            occurrences = 0
            if isinstance(particle, (ModelConcept, ModelAny)):
                elementDeclaration = particle.dereference()
                while iNextChild < len(children):
                    elt = children[iNextChild]
                    # children now only contains ModelObjects, no comments or other lxml elements
                    vQname = elt.vQname(modelXbrl) # takes care of elements inside inline or other instances
                    # for any, check namespace overlap
                    if ((isinstance(particle, ModelAny) and 
                         particle.allowsNamespace(vQname.namespaceURI)) or 
                        (isinstance(particle, ModelConcept) and
                         elementDeclaration is not None and 
                         (vQname == elementDeclaration.qname or
                          (vQname in modelXbrl.qnameConcepts and  
                           modelXbrl.qnameConcepts[vQname].substitutesForQname(elementDeclaration.qname))))):
                        occurrences += 1
                        validate(modelXbrl, elt, ixFacts=ixFacts)
                        iNextChild += 1
                        if occurrences == particle.maxOccurs:
                            break
                    elif not isinstance(particle, ModelAll):
                        break # done with this element
            else:  # group definition or compositor
                while occurrences < particle.maxOccurs:
                    iPrevChild = iNextChild
                    iNextChild, occurred, errDesc, errArgs = validateElementSequence(modelXbrl, particle, children, ixFacts, iNextChild)
                    if occurred:
                        # test if occurrence was because of minOccurs zero but no match occurred (HF 2012-09-07)
                        if occurred and iNextChild == iPrevChild and particle.minOccurs == 0: # nothing really occurred
                            break
                        occurrences += 1
                        if occurrences == particle.maxOccurs or iNextChild >= len(children):
                            break
                    else:
                        break
            if isinstance(compositor, ModelChoice):
                if occurrences > 0 and particle.minOccurs <= occurrences <= particle.maxOccurs:
                    return (iNextChild, True, None, None)  # choice has been selected
                else: # otherwise start again on next choice
                    if particle.minOccurs == 0:
                        anyChoiceHasMinOccurs0 = True
                    iNextChild = iStartingChild
            elif isinstance(compositor, ModelAll):
                if particle.minOccurs <= occurrences <= particle.maxOccurs:
                    allParticles.add(particle)  # particle found
                    moreParticlesPasses = True
                    break # advance to next all particle
            elif particle.minOccurs > 0 and errDesc:
                return (iNextChild, False, errDesc, errArgs)
            elif not particle.minOccurs <= occurrences <= particle.maxOccurs:
                return (iNextChild, False,
                        ("xmlSchema:elementOccurrencesError", 
                         _("%(compositor)s(%(particles)s) %(element)s occurred %(occurrences)s times, minOccurs=%(minOccurs)s, maxOccurs=%(maxOccurs)s, within %(parentElement)s")
                        if occurrences > 0 else
                         _("%(compositor)s(%(particles)s) content occurred %(occurrences)s times, minOccurs=%(minOccurs)s, maxOccurs=%(maxOccurs)s, within %(parentElement)s")
                         ),
                        dict(compositor=compositor, particles=particles, occurrences=occurrences, minOccurs=particle.minOccursStr, maxOccurs=particle.maxOccursStr))
    if isinstance(compositor, ModelAll):
        missingParticles = set(particles) - allParticles
        if missingParticles:
            return (iNextChild, False,
                    ("xmlSchema:missingParticlesError",
                     _("All(%(particles)s) missing at %(element)s, within %(parentElement)s")),
                    dict(particles=particles))
        occurred = True
    elif isinstance(compositor, ModelChoice):
        occurred = anyChoiceHasMinOccurs0 # deemed to have occurred if any choice had minoccurs=0
    else:
        occurred = True
    if isinstance(compositor, ModelType) and iNextChild < len(children):
        #if any(True for child in children[iNextChild:] if isinstance(child, ModelObject)): # any unexpected content elements
        if len(children) > iNextChild: # any unexpected content elements
            return (iNextChild, False,
                    ("xmlSchema:elementUnexpected",
                     _("%(compositor)s(%(particles)s) %(element)s unexpected, within %(parentElement)s")),
                    dict(compositor=compositor, particles=particles))
    return (iNextChild, occurred, None, None)
Exemple #6
0
 def stepAxis(self, op, p, sourceSequence):
     targetSequence = []
     for node in sourceSequence:
         if not isinstance(node,(ModelObject, etree._ElementTree, ModelAttribute)):
             raise XPathException(self.progHeader, 'err:XPTY0020', _('Axis step {0} context item is not a node: {1}').format(op, node))
         targetNodes = []
         if isinstance(p,QNameDef):
             ns = p.namespaceURI; localname = p.localName; axis = p.axis
             if p.isAttribute:
                 if isinstance(node,ModelObject):
                     attrTag = p.localName if p.unprefixed else p.clarkNotation
                     modelAttribute = None
                     try:
                         modelAttribute = node.xAttributes[attrTag]
                     except (AttributeError, TypeError, IndexError, KeyError):
                         # may be lax or deferred validated
                         try:
                             validate(node.modelXbrl, node, p)
                             modelAttribute = node.xAttributes[attrTag]
                         except (AttributeError, TypeError, IndexError, KeyError):
                             pass
                     if modelAttribute is None:
                         value = node.get(attrTag)
                         if value is not None:
                             targetNodes.append(ModelAttribute(node,p.clarkNotation,UNKNOWN,value,value,value))
                     elif modelAttribute.xValid >= VALID:
                             targetNodes.append(modelAttribute)
             elif op == '/' or op is None:
                 if axis is None or axis == "child":
                     if isinstance(node,(ModelObject, etree._ElementTree)):
                         targetNodes = XmlUtil.children(node, ns, localname)
                 elif axis == "parent":
                     if isinstance(node,ModelAttribute):
                         paretNode = [ node.modelElement ]
                     else:
                         parentNode = [ XmlUtil.parent(node) ]
                     if (isinstance(node,ModelObject) and
                             (not ns or ns == parentNode.namespaceURI or ns == "*") and
                         (localname == parentNode.localName or localname == "*")):
                         targetNodes = [ parentNode ]
                 elif axis == "self":
                     if (isinstance(node,ModelObject) and
                             (not ns or ns == node.namespaceURI or ns == "*") and
                         (localname == node.localName or localname == "*")):
                         targetNodes = [ node ]
                 elif axis.startswith("descendant"):
                     if isinstance(node,(ModelObject, etree._ElementTree)):
                         targetNodes = XmlUtil.descendants(node, ns, localname)
                         if (axis.endswith("-or-self") and
                             isinstance(node,ModelObject) and
                             (not ns or ns == node.namespaceURI or ns == "*") and
                             (localname == node.localName or localname == "*")):
                             targetNodes.append(node) 
                 elif axis.startswith("ancestor"):
                     if isinstance(node,ModelObject):
                         targetNodes = [ancestor
                                        for ancestor in XmlUtil.ancestors(node)
                                        if ((not ns or ns == ancestor.namespaceURI or ns == "*") and
                                            (localname == ancestor.localName or localname == "*"))]
                         if (axis.endswith("-or-self") and
                             isinstance(node,ModelObject) and
                             (not ns or ns == node.namespaceURI or ns == "*") and
                             (localname == node.localName or localname == "*")):
                             targetNodes.insert(0, node) 
                 elif axis.endswith("-sibling"):
                     if isinstance(node,ModelObject):
                         targetNodes = [sibling
                                        for sibling in node.itersiblings(preceding=axis.startswith("preceding"))
                                        if ((not ns or ns == sibling.namespaceURI or ns == "*") and
                                            (localname == sibling.localName or localname == "*"))]
                 elif axis == "preceding":
                     if isinstance(node,ModelObject):
                         for preceding in node.getroottree().iter():
                             if preceding == node:
                                 break
                             elif ((not ns or ns == preceding.namespaceURI or ns == "*") and
                                   (localname == preceding.localName or localname == "*")):
                                 targetNodes.append(preceding)
                 elif axis == "following":
                     if isinstance(node,ModelObject):
                         foundNode = False
                         for following in node.getroottree().iter():
                             if following == node:
                                 foundNode = True
                             elif (foundNode and
                                   (not ns or ns == following.namespaceURI or ns == "*") and
                                   (localname == following.localName or localname == "*")):
                                 targetNodes.append(following)
             elif op == '//':
                 if isinstance(node,(ModelObject, etree. _ElementTree)):
                     targetNodes = XmlUtil.descendants(node, ns, localname)
             elif op == '..':
                 if isinstance(node,ModelAttribute):
                     targetNodes = [ node.modelElement ]
                 else:
                     targetNodes = [ XmlUtil.parent(node) ]
         elif isinstance(p, OperationDef) and isinstance(p.name,QNameDef):
             if isinstance(node,ModelObject):
                 if p.name.localName == "text":
                     targetNodes = [XmlUtil.text(node)]
                 # todo: add element, attribute, node, etc...
         elif p == '*':  # wildcard
             if op == '/' or op is None:
                 if isinstance(node,(ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.children(node, '*', '*')
             elif op == '//':
                 if isinstance(node,(ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.descendants(node, '*', '*')
         targetSequence.extend(targetNodes)
     return targetSequence
Exemple #7
0
 def stepAxis(self, op, p, sourceSequence):
     targetSequence = []
     for node in sourceSequence:
         if not isinstance(
                 node, (ModelObject, etree._ElementTree, ModelAttribute)):
             raise XPathException(
                 self.progHeader, 'err:XPTY0020',
                 _('Axis step {0} context item is not a node: {1}').format(
                     op, node))
         targetNodes = []
         if isinstance(p, QNameDef):
             ns = p.namespaceURI
             localname = p.localName
             if p.isAttribute:
                 if isinstance(node, ModelObject):
                     attrTag = p.localName if p.unprefixed else p.clarkNotation
                     modelAttribute = None
                     try:
                         modelAttribute = node.xAttributes[attrTag]
                     except (AttributeError, TypeError, IndexError,
                             KeyError):
                         # may be lax or deferred validated
                         try:
                             validate(node.modelXbrl, node, p)
                             modelAttribute = node.xAttributes[attrTag]
                         except (AttributeError, TypeError, IndexError,
                                 KeyError):
                             pass
                     if modelAttribute is None:
                         value = node.get(attrTag)
                         if value is not None:
                             targetNodes.append(
                                 ModelAttribute(node, p.clarkNotation,
                                                UNKNOWN, value, value,
                                                value))
                     elif modelAttribute.xValid >= VALID:
                         targetNodes.append(modelAttribute)
             elif op == '/' or op is None:
                 if isinstance(node, (ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.children(node, ns, localname)
             elif op == '//':
                 if isinstance(node, (ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.descendants(node, ns, localname)
             elif op == '..':
                 if isinstance(node, ModelAttribute):
                     targetNodes = [node.modelElement]
                 else:
                     targetNodes = [XmlUtil.parent(node)]
         elif isinstance(p, OperationDef) and isinstance(p.name, QNameDef):
             if isinstance(node, ModelObject):
                 if p.name.localName == "text":
                     targetNodes = [XmlUtil.text(node)]
                 # todo: add element, attribute, node, etc...
         elif p == '*':  # wildcard
             if op == '/' or op is None:
                 if isinstance(node, (ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.children(node, '*', '*')
             elif op == '//':
                 if isinstance(node, (ModelObject, etree._ElementTree)):
                     targetNodes = XmlUtil.descendants(node, '*', '*')
         targetSequence.extend(targetNodes)
     return targetSequence
Exemple #8
0
def validateElementSequence(modelXbrl, compositor, children, iNextChild=0):
    particles = compositor.dereference().particles
    iStartingChild = iNextChild
    errDesc = None
    if isinstance(compositor, ModelAll):
        allParticles = set()  # elements required
        iNextAfterAll = iStartingChild
    elif isinstance(compositor, ModelChoice):
        anyChoiceHasMinOccurs0 = False
    moreParticlesPasses = True
    while moreParticlesPasses:
        moreParticlesPasses = False
        for particle in particles:
            occurences = 0
            if isinstance(particle, (ModelConcept, ModelAny)):
                elementDeclaration = particle.dereference()
                while iNextChild < len(children):
                    elt = children[iNextChild]
                    if isinstance(elt, ModelObject):
                        # for any, check namespace overlap
                        if (isinstance(particle, ModelAny) or
                            (elementDeclaration is not None and
                             (elt.qname == elementDeclaration.qname
                              or elt.elementDeclaration.substitutesForQname(
                                  elementDeclaration.qname)))):
                            occurences += 1
                            validate(modelXbrl, elt)
                            iNextChild += 1
                            if occurences == particle.maxOccurs:
                                break
                        elif not isinstance(particle, ModelAll):
                            break  # done with this element
                    else:  # comment or processing instruction, skip over it
                        iNextChild += 1
            else:  # group definition or compositor
                while occurences < particle.maxOccurs:
                    iPrevChild = iNextChild
                    iNextChild, occured, errDesc, errArgs = validateElementSequence(
                        modelXbrl, particle, children, iNextChild)
                    if occured:
                        occurences += 1
                        if occurences == particle.maxOccurs or iNextChild >= len(
                                children):
                            break
                    else:
                        break
            if isinstance(compositor, ModelChoice):
                if occurences > 0 and particle.minOccurs <= occurences <= particle.maxOccurs:
                    return (iNextChild, True, None, None
                            )  # choice has been selected
                else:  # otherwise start again on next choice
                    if particle.minOccurs == 0:
                        anyChoiceHasMinOccurs0 = True
                    iNextChild = iStartingChild
            elif isinstance(compositor, ModelAll):
                if particle.minOccurs <= occurences <= particle.maxOccurs:
                    allParticles.add(particle)  # particle found
                    moreParticlesPasses = True
                    break  # advance to next all particle
            elif particle.minOccurs > 0 and errDesc:
                return (iNextChild, False, errDesc, errArgs)
            elif not particle.minOccurs <= occurences <= particle.maxOccurs:
                return (iNextChild, False, (
                    "xmlSchema:elementOccurencesError",
                    _("%(compositor)s(%(particles)s) %(element)s occured %(occurences)s times, minOccurs=%(minOccurs)s, maxOccurs=%(maxOccurs)s, within %(parentElement)s"
                      )),
                        dict(compositor=compositor,
                             particles=particles,
                             occurences=occurences,
                             minOccurs=particle.minOccursStr,
                             maxOccurs=particle.maxOccursStr))
    if isinstance(compositor, ModelAll):
        missingParticles = set(particles) - allParticles
        if missingParticles:
            return (iNextChild, False, (
                "xmlSchema:missingParticlesError",
                _("All(%(particles)s) missing at %(element)s, within %(parentElement)s"
                  )), dict(particles=particles))
        occured = True
    elif isinstance(compositor, ModelChoice):
        occured = anyChoiceHasMinOccurs0  # deemed to have occured if any choice had minoccurs=0
    else:
        occured = True
    if isinstance(compositor, ModelType) and iNextChild < len(children):
        elt = children[iNextChild]
        eltChildren = elt.modelTupleFacts if isinstance(
            elt, ModelInlineFact) else elt
        if any(True for child in eltChildren if isinstance(
                child, ModelObject)):  # any unexpected content elements
            return (iNextChild, False, (
                "xmlSchema:elementUnexpected",
                _("%(compositor)s(%(particles)s) %(element)s unexpected, within %(parentElement)s"
                  )), dict(compositor=compositor, particles=particles))
    return (iNextChild, occured, None, None)