Example #1
0
 def checkHierarchyConstraints(elt):
     constraints = ixHierarchyConstraints.get(elt.localName)
     if constraints:
         for _rel, names in constraints:
             reqt = _rel[0]
             rel = _rel[1:]
             if reqt in ('&', '^', '1'):
                 nameFilter = ('*', )
             else:
                 nameFilter = names
             if nameFilter == ('*', ):
                 namespaceFilter = namespacePrefix = '*'
             elif len(nameFilter) == 1 and "}" in nameFilter[
                     0] and nameFilter[0][0] == "{":
                 namespaceFilter, _sep, nameFilter = nameFilter[0][
                     1:].partition("}")
                 namespacePrefix = XmlUtil.xmlnsprefix(elt, namespaceFilter)
             else:
                 namespaceFilter = elt.namespaceURI
                 namespacePrefix = elt.prefix
             relations = {
                 "ancestor": XmlUtil.ancestor,
                 "parent": XmlUtil.parent,
                 "child-choice": XmlUtil.children,
                 "child-sequence": XmlUtil.children,
                 "child-or-text": XmlUtil.children,
                 "descendant": XmlUtil.descendants
             }[rel](elt, namespaceFilter, nameFilter)
             if rel in ("ancestor", "parent"):
                 if relations is None: relations = []
                 else: relations = [relations]
             if rel == "child-or-text":
                 relations += XmlUtil.innerTextNodes(elt,
                                                     ixExclude=True,
                                                     ixEscape=False,
                                                     ixContinuation=False)
             issue = ''
             if reqt in ('^', ):
                 if not any(r.localName in names
                            and r.namespaceURI == elt.namespaceURI
                            for r in relations):
                     issue = " and is missing one of " + ', '.join(names)
             if reqt in ('1', ) and not elt.isNil:
                 if sum(r.localName in names
                        and r.namespaceURI == elt.namespaceURI
                        for r in relations) != 1:
                     issue = " and must have exactly one of " + ', '.join(
                         names)
             if reqt in ('&', '^'):
                 disallowed = [
                     str(r.elementQname) for r in relations
                     if not (r.tag in names or
                             (r.localName in names
                              and r.namespaceURI == elt.namespaceURI))
                 ]
                 if disallowed:
                     issue += " and may not have " + ", ".join(disallowed)
                 elif rel == "child-sequence":
                     sequencePosition = 0
                     for i, r in enumerate(relations):
                         rPos = names.index(str(r.localName))
                         if rPos < sequencePosition:
                             issue += " and is out of sequence: " + str(
                                 r.elementQname)
                         else:
                             sequencePosition = rPos
             if reqt == '?' and len(relations) > 1:
                 issue = " may only have 0 or 1 but {0} present ".format(
                     len(relations))
             if reqt == '+' and len(relations) == 0:
                 issue = " must have at least 1 but none present "
             disallowedChildText = bool(
                 reqt == '&' and rel in ("child-sequence", "child-choice")
                 and elt.textValue.strip())
             if ((reqt == '+' and not relations)
                     or (reqt == '-' and relations) or (issue)
                     or disallowedChildText):
                 code = "{}:{}".format(
                     ixSect[elt.namespaceURI].get(elt.localName,
                                                  "other")["constraint"],
                     {
                         'ancestor': "ancestorNode",
                         'parent': "parentNode",
                         'child-choice': "childNodes",
                         'child-sequence': "childNodes",
                         'child-or-text': "childNodesOrText",
                         'descendant': "descendantNodes"
                     }[rel] + {
                         '+': "Required",
                         '-': "Disallowed",
                         '&': "Allowed",
                         '^': "Specified",
                         '1': "Specified"
                     }.get(reqt, "Specified"))
                 msg = _("Inline XBRL ix:{0} {1} {2} {3} {4} element{5}"
                         ).format(
                             elt.localName, {
                                 '+': "must",
                                 '-': "may not",
                                 '&': "may only",
                                 '?': "may",
                                 '+': "must",
                                 '^': "must",
                                 '1': "must"
                             }[reqt], {
                                 'ancestor': "be nested in",
                                 'parent': "have parent",
                                 'child-choice': "have child",
                                 'child-sequence': "have child",
                                 'child-or-text': "have child or text,",
                                 'descendant': "have as descendant"
                             }[rel],
                             '' if rel == 'child-or-text' else ', '.join(
                                 str(r.elementQname) for r in relations) if
                             names == ('*', ) and relations else ", ".join(
                                 "{}:{}".format(namespacePrefix, n)
                                 for n in names), issue,
                             " and no child text (\"{}\")".format(
                                 elt.textValue.strip()[:32])
                             if disallowedChildText else "")
                 modelXbrl.error(
                     code,
                     msg,
                     modelObject=[elt] + relations,
                     requirement=reqt,
                     messageCodes=
                     ("ix{ver.sect}:ancestorNode{Required|Disallowed}",
                      "ix{ver.sect}:childNodesOrTextRequired",
                      "ix{ver.sect}:childNodes{Required|Disallowed|Allowed}",
                      "ix{ver.sect}:descendantNodesDisallowed",
                      "ix{ver.sect}:parentNodeRequired"))
     # other static element checks (that don't require a complete object model, context, units, etc
     if elt.localName == "nonFraction":
         childElts = XmlUtil.children(elt, '*', '*')
         hasText = (elt.text or "") or any(
             (childElt.tail or "") for childElt in childElts)
         if elt.isNil:
             ancestorNonFractions = XmlUtil.ancestors(
                 elt, _ixNS, elt.localName)
             if ancestorNonFractions:
                 modelXbrl.error(
                     ixMsgCode("nonFractionAncestors", elt),
                     _("Fact %(fact)s is a nil nonFraction and MUST not have an ancestor ix:nonFraction"
                       ),
                     modelObject=[elt] + ancestorNonFractions,
                     fact=elt.qname)
             if childElts or hasText:
                 modelXbrl.error(
                     ixMsgCode("nonFractionTextAndElementChildren", elt),
                     _("Fact %(fact)s is a nil nonFraction and MUST not have an child elements or text"
                       ),
                     modelObject=[elt] + childElts,
                     fact=elt.qname)
                 elt.setInvalid(
                 )  # prevent further validation or cascading errors
         else:
             if ((childElts and
                  (len(childElts) != 1 or childElts[0].namespaceURI != _ixNS
                   or childElts[0].localName != "nonFraction"))
                     or (childElts and hasText)):
                 modelXbrl.error(
                     ixMsgCode("nonFractionTextAndElementChildren", elt),
                     _("Fact %(fact)s is a non-nil nonFraction and MUST have exactly one ix:nonFraction child element or text."
                       ),
                     modelObject=[elt] + childElts,
                     fact=elt.qname)
                 elt.setInvalid()
     if elt.localName == "fraction":
         if elt.isNil:
             ancestorFractions = XmlUtil.ancestors(elt, _ixNS,
                                                   elt.localName)
             if ancestorFractions:
                 modelXbrl.error(
                     ixMsgCode("fractionAncestors", elt),
                     _("Fact %(fact)s is a nil fraction and MUST not have an ancestor ix:fraction"
                       ),
                     modelObject=[elt] + ancestorFractions,
                     fact=elt.qname)
         else:
             nonFrChildren = [
                 e for e in XmlUtil.children(elt, _ixNS, '*')
                 if e.localName not in ("fraction", "numerator",
                                        "denominator")
             ]
             if nonFrChildren:
                 modelXbrl.error(
                     ixMsgCode("fractionElementChildren", elt),
                     _("Fact %(fact)s is a non-nil fraction and not have any child elements except ix:fraction, ix:numerator and ix:denominator: %(children)s"
                       ),
                     modelObject=[elt] + nonFrChildren,
                     fact=elt.qname,
                     children=", ".join(e.localName for e in nonFrChildren))
             for ancestorFraction in XmlUtil.ancestors(
                     elt, XbrlConst.ixbrl11, "fraction"):  # only ix 1.1
                 if normalizeSpace(elt.get("unitRef")) != normalizeSpace(
                         ancestorFraction.get("unitRef")):
                     modelXbrl.error(
                         ixMsgCode("fractionNestedUnitRef", elt),
                         _("Fact %(fact)s fraction and ancestor fractions must have matching unitRefs: %(unitRef)s, %(unitRef2)s"
                           ),
                         modelObject=[elt] + nonFrChildren,
                         fact=elt.qname,
                         unitRef=elt.get("unitRef"),
                         unitRef2=ancestorFraction.get("unitRef"))
     if elt.localName in ("nonFraction", "numerator", "denominator",
                          "nonNumeric"):
         fmt = elt.format
         if fmt:
             if fmt in _customTransforms:
                 pass
             elif fmt.namespaceURI not in FunctionIxt.ixtNamespaceFunctions:
                 modelXbrl.error(
                     ixMsgCode("invalidTransformation",
                               elt,
                               sect="validation"),
                     _("Fact %(fact)s has unrecognized transformation namespace %(namespace)s"
                       ),
                     modelObject=elt,
                     fact=elt.qname,
                     transform=fmt,
                     namespace=fmt.namespaceURI)
                 elt.setInvalid()
             elif fmt.localName not in FunctionIxt.ixtNamespaceFunctions[
                     fmt.namespaceURI]:
                 modelXbrl.error(
                     ixMsgCode("invalidTransformation",
                               elt,
                               sect="validation"),
                     _("Fact %(fact)s has unrecognized transformation name %(name)s"
                       ),
                     modelObject=elt,
                     fact=elt.qname,
                     transform=fmt,
                     name=fmt.localName)
                 elt.setInvalid()
Example #2
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:
                             xmlValidate(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
Example #3
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:
                             xmlValidate(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
Example #4
0
 def checkHierarchyConstraints(elt):
     constraints = ixHierarchyConstraints.get(elt.localName)
     if constraints:
         for _rel, names in constraints:
             reqt = _rel[0]
             rel = _rel[1:]
             if reqt in ('&', '^', '1'):
                 nameFilter = ('*',)
             else:
                 nameFilter = names
             if nameFilter == ('*',):
                 namespaceFilter = namespacePrefix = '*'
             elif len(nameFilter) == 1 and "}" in nameFilter[0] and nameFilter[0][0] == "{":
                 namespaceFilter, _sep, nameFilter = nameFilter[0][1:].partition("}")
                 namespacePrefix = XmlUtil.xmlnsprefix(elt,namespaceFilter)
             else:
                 namespaceFilter = elt.namespaceURI
                 namespacePrefix = elt.prefix
             relations = {"ancestor": XmlUtil.ancestor, 
                          "parent": XmlUtil.parent, 
                          "child-choice": XmlUtil.children, 
                          "child-sequence": XmlUtil.children,
                          "child-or-text": XmlUtil.children,
                          "descendant": XmlUtil.descendants}[rel](
                         elt, 
                         namespaceFilter,
                         nameFilter)
             if rel in ("ancestor", "parent"):
                 if relations is None: relations = []
                 else: relations = [relations]
             if rel == "child-or-text":
                 relations += XmlUtil.innerTextNodes(elt, ixExclude=True, ixEscape=False, ixContinuation=False, ixResolveUris=False)
             issue = ''
             if reqt in ('^',):
                 if not any(r.localName in names and r.namespaceURI == elt.namespaceURI
                            for r in relations):
                     issue = " and is missing one of " + ', '.join(names)
             if reqt in ('1',) and not elt.isNil:
                 if sum(r.localName in names and r.namespaceURI == elt.namespaceURI
                        for r in relations) != 1:
                     issue = " and must have exactly one of " + ', '.join(names)
             if reqt in ('&', '^'):
                 disallowed = [str(r.elementQname)
                               for r in relations
                               if not (r.tag in names or
                                       (r.localName in names and r.namespaceURI == elt.namespaceURI))]
                 if disallowed:
                     issue += " and may not have " + ", ".join(disallowed)
                 elif rel == "child-sequence":
                     sequencePosition = 0
                     for i, r in enumerate(relations):
                         rPos = names.index(str(r.localName))
                         if rPos < sequencePosition:
                             issue += " and is out of sequence: " + str(r.elementQname)
                         else:
                             sequencePosition = rPos
             if reqt == '?' and len(relations) > 1:
                 issue = " may only have 0 or 1 but {0} present ".format(len(relations))
             if reqt == '+' and len(relations) == 0:
                 issue = " must have at least 1 but none present "
             disallowedChildText = bool(reqt == '&' and 
                                        rel in ("child-sequence", "child-choice") 
                                        and elt.textValue.strip())
             if ((reqt == '+' and not relations) or
                 (reqt == '-' and relations) or
                 (issue) or disallowedChildText):
                 code = "{}:{}".format(ixSect[elt.namespaceURI].get(elt.localName,"other")["constraint"], {
                        'ancestor': "ancestorNode",
                        'parent': "parentNode",
                        'child-choice': "childNodes",
                        'child-sequence': "childNodes",
                        'child-or-text': "childNodesOrText",
                        'descendant': "descendantNodes"}[rel] + {
                         '+': "Required",
                         '-': "Disallowed",
                         '&': "Allowed",
                         '^': "Specified",
                         '1': "Specified"}.get(reqt, "Specified"))
                 msg = _("Inline XBRL ix:{0} {1} {2} {3} {4} element{5}").format(
                             elt.localName,
                             {'+': "must", '-': "may not", '&': "may only",
                              '?': "may", '+': "must", '^': "must", '1': "must"}[reqt],
                             {'ancestor': "be nested in",
                              'parent': "have parent",
                              'child-choice': "have child",
                              'child-sequence': "have child",
                              'child-or-text': "have child or text,",
                              'descendant': "have as descendant"}[rel],
                             '' if rel == 'child-or-text' else
                             ', '.join(str(r.elementQname) for r in relations)
                             if names == ('*',) and relations else
                             ", ".join("{}:{}".format(namespacePrefix, n) for n in names),
                             issue,
                             " and no child text (\"{}\")".format(elt.textValue.strip()[:32]) if disallowedChildText else "")
                 modelXbrl.error(code, msg, 
                                 modelObject=[elt] + relations, requirement=reqt,
                                 messageCodes=("ix{ver.sect}:ancestorNode{Required|Disallowed}",
                                               "ix{ver.sect}:childNodesOrTextRequired",
                                               "ix{ver.sect}:childNodes{Required|Disallowed|Allowed}",
                                               "ix{ver.sect}:descendantNodesDisallowed",
                                               "ix{ver.sect}:parentNodeRequired"))
     # other static element checks (that don't require a complete object model, context, units, etc
     if elt.localName == "nonFraction":
         childElts = XmlUtil.children(elt, '*', '*')
         hasText = (elt.text or "") or any((childElt.tail or "") for childElt in childElts)
         if elt.isNil:
             ancestorNonFractions = XmlUtil.ancestors(elt, _ixNS, elt.localName)
             if ancestorNonFractions:
                 modelXbrl.error(ixMsgCode("nonFractionAncestors", elt),
                     _("Fact %(fact)s is a nil nonFraction and MUST not have an ancestor ix:nonFraction"),
                     modelObject=[elt] + ancestorNonFractions, fact=elt.qname)
             if childElts or hasText:
                 modelXbrl.error(ixMsgCode("nonFractionTextAndElementChildren", elt),
                     _("Fact %(fact)s is a nil nonFraction and MUST not have an child elements or text"),
                     modelObject=[elt] + childElts, fact=elt.qname)
                 elt.setInvalid() # prevent further validation or cascading errors
         else:
             if ((childElts and (len(childElts) != 1 or childElts[0].namespaceURI != _ixNS or childElts[0].localName != "nonFraction")) or
                 (childElts and hasText)):
                 modelXbrl.error(ixMsgCode("nonFractionTextAndElementChildren", elt),
                     _("Fact %(fact)s is a non-nil nonFraction and MUST have exactly one ix:nonFraction child element or text."),
                     modelObject=[elt] + childElts, fact=elt.qname)
                 elt.setInvalid()
     if elt.localName == "fraction":
         if elt.isNil:
             ancestorFractions = XmlUtil.ancestors(elt, _ixNS, elt.localName)
             if ancestorFractions:
                 modelXbrl.error(ixMsgCode("fractionAncestors", elt),
                     _("Fact %(fact)s is a nil fraction and MUST not have an ancestor ix:fraction"),
                     modelObject=[elt] + ancestorFractions, fact=elt.qname)
         else:
             nonFrChildren = [e for e in XmlUtil.children(elt, _ixNS, '*') if e.localName not in ("fraction", "numerator", "denominator")]
             if nonFrChildren:
                 modelXbrl.error(ixMsgCode("fractionElementChildren", elt),
                     _("Fact %(fact)s is a non-nil fraction and not have any child elements except ix:fraction, ix:numerator and ix:denominator: %(children)s"),
                     modelObject=[elt] + nonFrChildren, fact=elt.qname, children=", ".join(e.localName for e in nonFrChildren))
             for ancestorFraction in XmlUtil.ancestors(elt, XbrlConst.ixbrl11, "fraction"): # only ix 1.1
                 if normalizeSpace(elt.get("unitRef")) != normalizeSpace(ancestorFraction.get("unitRef")):
                     modelXbrl.error(ixMsgCode("fractionNestedUnitRef", elt),
                         _("Fact %(fact)s fraction and ancestor fractions must have matching unitRefs: %(unitRef)s, %(unitRef2)s"),
                         modelObject=[elt] + nonFrChildren, fact=elt.qname, unitRef=elt.get("unitRef"), unitRef2=ancestorFraction.get("unitRef"))
     if elt.localName in ("nonFraction", "numerator", "denominator", "nonNumeric"):
         fmt = elt.format
         if fmt:
             if fmt in _customTransforms:
                 pass
             elif fmt.namespaceURI not in FunctionIxt.ixtNamespaceFunctions:
                 modelXbrl.error(ixMsgCode("invalidTransformation", elt, sect="validation"),
                     _("Fact %(fact)s has unrecognized transformation namespace %(namespace)s"),
                     modelObject=elt, fact=elt.qname, transform=fmt, namespace=fmt.namespaceURI)
                 elt.setInvalid()
             elif fmt.localName not in FunctionIxt.ixtNamespaceFunctions[fmt.namespaceURI]:
                 modelXbrl.error(ixMsgCode("invalidTransformation", elt, sect="validation"),
                     _("Fact %(fact)s has unrecognized transformation name %(name)s"),
                     modelObject=elt, fact=elt.qname, transform=fmt, name=fmt.localName)
                 elt.setInvalid()
Example #5
0
def checkDTSdocument(val, modelDocument, isFilingDocument):
    for hrefElt, _hrefedDoc, hrefId in modelDocument.hrefObjects:
        if hrefId:  #check scheme regardless of whether document loaded
            # check all xpointer schemes
            for scheme, _path in XmlUtil.xpointerSchemes(hrefId):
                if scheme == "element" and val.validateDisclosureSystem:
                    val.modelXbrl.error(
                        ("EFM.6.03.06", "GFM.1.01.03"),
                        _("Href %(elementHref)s may only have shorthand xpointers"
                          ),
                        edgarCode="cp-0306-Href-Xpointers",
                        modelObject=hrefElt,
                        elementHref=hrefElt.get(
                            "{http://www.w3.org/1999/xlink}href"))

    if not isFilingDocument:
        return  # not a filing's extension document

    if modelDocument.type == ModelDocument.Type.SCHEMA:
        if modelDocument.targetNamespace is not None and len(
                modelDocument.targetNamespace) > 85:
            l = len(modelDocument.targetNamespace.encode("utf-8"))
            if l > 255:
                val.modelXbrl.error(
                    "EFM.6.07.30",
                    _("Shorten this declaration URI from %(length)s to 255 bytes or fewer in UTF-8: %(value)s."
                      ),
                    edgarCode="du-0730-uri-length-limit",
                    modelObject=modelDocument.xmlRootElement,
                    length=l,
                    targetNamespace=modelDocument.targetNamespace,
                    value=modelDocument.targetNamespace)

    if modelDocument.type in (ModelDocument.Type.SCHEMA,
                              ModelDocument.Type.LINKBASE):
        isSchema = modelDocument.type == ModelDocument.Type.SCHEMA
        if isSchema:
            for elt in modelDocument.xmlRootElement.iter(
                    tag="{http://www.w3.org/2001/XMLSchema}*"):
                if elt.namespaceURI == XbrlConst.xsd:
                    localName = elt.localName
                    if localName in {"element", "complexType", "simpleType"}:
                        name = elt.get("name")
                        if name and len(name) > 64:
                            l = len(name.encode("utf-8"))
                            if l > 200:
                                val.modelXbrl.error(
                                    "EFM.6.07.29",
                                    _("Shorten this declaration name from %(length)s to 200 bytes or fewer in UTF-8: %(name)s"
                                      ),
                                    edgarCode="du-0729-name-length-limit",
                                    modelObject=elt,
                                    element=localName,
                                    name=name,
                                    length=l)

    for elt in modelDocument.xmlRootElement.iter():
        if isinstance(elt, ModelObject):
            xlinkType = elt.get("{http://www.w3.org/1999/xlink}type")
            xlinkRole = elt.get("{http://www.w3.org/1999/xlink}role")
            if elt.namespaceURI == XbrlConst.link:
                # check schema roleTypes
                if elt.localName in ("roleType", "arcroleType"):
                    uriAttr = {
                        "roleType": "roleURI",
                        "arcroleType": "arcroleURI"
                    }[elt.localName]
                    roleURI = elt.get(uriAttr)
                    if len(roleURI) > 85:
                        l = len(roleURI.encode("utf-8"))
                        if l > 255:
                            val.modelXbrl.error(
                                "EFM.6.07.30",
                                _("Shorten this declaration URI from %(length)s to 255 bytes or fewer in UTF-8: %(value)s."
                                  ),
                                edgarCode="du-0730-uri-length-limit",
                                modelObject=elt,
                                element=elt.qname,
                                attribute=uriAttr,
                                length=l,
                                roleURI=roleURI,
                                value=roleURI)

                if elt.localName == "arcroleRef":
                    refUri = elt.get("arcroleURI")
                    hrefAttr = elt.get("{http://www.w3.org/1999/xlink}href")
                    hrefUri, hrefId = UrlUtil.splitDecodeFragment(hrefAttr)
                    if hrefUri not in val.disclosureSystem.standardTaxonomiesDict:
                        val.modelXbrl.error(
                            ("EFM.6.09.06", "GFM.1.04.06"),
                            _("An arcroleRef element refers to %(xlinkHref)s, an arcrole, %(refURI)s, that is not defined in a standard taxonomy. "
                              "Please recheck submission."),
                            edgarCode="fs-0906-Custom-Arcrole-Referenced",
                            modelObject=elt,
                            refURI=refUri,
                            xlinkHref=hrefUri)
            if modelDocument.type == ModelDocument.Type.INLINEXBRL and elt.namespaceURI in XbrlConst.ixbrlAll:
                if elt.localName == "footnote":
                    if val.validateGFM:
                        if elt.get("{http://www.w3.org/1999/xlink}arcrole"
                                   ) != XbrlConst.factFootnote:
                            # must be in a nonDisplay div
                            if not any(
                                    inlineDisplayNonePattern.search(
                                        e.get("style") or "")
                                    for e in XmlUtil.ancestors(
                                        elt, XbrlConst.xhtml, "div")):
                                val.modelXbrl.error(
                                    ("EFM.N/A", "GFM:1.10.16"),
                                    _("Inline XBRL footnote %(footnoteID)s must be in non-displayable div due to arcrole %(arcrole)s"
                                      ),
                                    modelObject=elt,
                                    footnoteID=elt.get("footnoteID"),
                                    arcrole=elt.get(
                                        "{http://www.w3.org/1999/xlink}arcrole"
                                    ))

                        if not elt.get(
                                "{http://www.w3.org/XML/1998/namespace}lang"):
                            val.modelXbrl.error(
                                ("EFM.N/A", "GFM:1.10.13"),
                                _("Inline XBRL footnote %(footnoteID)s is missing an xml:lang attribute"
                                  ),
                                modelObject=elt,
                                footnoteID=id)
            if xlinkType == "extended":
                if not xlinkRole or xlinkRole == "":
                    val.modelXbrl.error(
                        ("EFM.6.09.04", "GFM.1.04.04"),
                        "The %(element)s element requires an xlink:role such as the default, 'http://www.xbrl.org/2003/role/label'.  "
                        "Please recheck submission.",
                        edgarCode="fs-0904-Resource-Role-Missing",
                        modelObject=elt,
                        element=elt.qname)
                if not val.extendedElementName:
                    val.extendedElementName = elt.qname
                elif val.extendedElementName != elt.qname:
                    val.modelXbrl.error(
                        ("EFM.6.09.07", "GFM:1.04.07"),
                        _("Your filing contained extended type links with roles of different namesapces and local names, %(element)s "
                          "and %(element2)s in the same linkbase, %(refUrl)s.  Please recheck your submission and ensure that all "
                          "extended-type links in a single linkbase have the same namespace and local name."
                          ),
                        edgarCode="cp-0907-Linkbases-Distinct",
                        refUrl=elt.modelDocument.basename,
                        modelObject=elt,
                        element=elt.qname,
                        element2=val.extendedElementName)
            elif xlinkType == "resource":
                if not xlinkRole:
                    val.modelXbrl.error(
                        ("EFM.6.09.04", "GFM.1.04.04"),
                        _("The %(element)s element requires an xlink:role such as the default, 'http://www.xbrl.org/2003/role/label'.  "
                          "Please recheck submission."),
                        edgarCode="fs-0904-Resource-Role-Missing",
                        modelObject=elt,
                        element=elt.qname)
                elif not XbrlConst.isStandardRole(xlinkRole):
                    modelsRole = val.modelXbrl.roleTypes.get(xlinkRole)
                    if (modelsRole is None or len(modelsRole) == 0
                            or modelsRole[0].modelDocument.targetNamespace
                            not in val.disclosureSystem.standardTaxonomiesDict
                        ):
                        val.modelXbrl.error(
                            ("EFM.6.09.05", "GFM.1.04.05"),
                            _("The %(element)s element has a role, %(roleDefinition)s, that is not defined in a standard taxonomy, "
                              "resource labeled %(xlinkLabel)s.  Please recheck submission."
                              ),
                            edgarCode="fs-0905-Custom-Resource-Role-Used",
                            modelObject=elt,
                            xlinkLabel=elt.get(
                                "{http://www.w3.org/1999/xlink}label"),
                            role=xlinkRole,
                            element=elt.qname,
                            roleDefinition=val.modelXbrl.roleTypeDefinition(
                                xlinkRole))
            elif xlinkType == "arc":
                if elt.get("priority") is not None:
                    priority = elt.get("priority")
                    try:
                        if int(priority) >= 10:
                            val.modelXbrl.error(
                                ("EFM.6.09.09", "GFM.1.04.08"),
                                _("The priority attribute %(priority)s has a value of ten or greater, on arc %(arcElement)s from %(xlinkFrom)s to %(xlinkTo)s. "
                                  "Please change the priority to value less than 10 and resubmit."
                                  ),
                                edgarCode=
                                "du-0909-Relationship-Priority-Not-Less-Than-Ten",
                                modelObject=elt,
                                arcElement=elt.qname,
                                xlinkFrom=elt.get(
                                    "{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get(
                                    "{http://www.w3.org/1999/xlink}to"),
                                priority=priority)
                    except (ValueError):
                        val.modelXbrl.error(
                            ("EFM.6.09.09", "GFM.1.04.08"),
                            _("The priority attribute %(priority)s has a value of ten or greater, on arc %(arcElement)s from %(xlinkFrom)s to %(xlinkTo)s. "
                              "Please change the priority to value less than 10 and resubmit."
                              ),
                            edgarCode=
                            "du-0909-Relationship-Priority-Not-Less-Than-Ten",
                            modelObject=elt,
                            arcElement=elt.qname,
                            xlinkFrom=elt.get(
                                "{http://www.w3.org/1999/xlink}from"),
                            xlinkTo=elt.get(
                                "{http://www.w3.org/1999/xlink}to"),
                            priority=priority)
                if elt.namespaceURI == XbrlConst.link:
                    if elt.localName == "presentationArc" and not elt.get(
                            "order"):
                        val.modelXbrl.error(
                            ("EFM.6.12.01", "GFM.1.06.01"),
                            _("The presentation relationship from %(conceptFrom)s to %(conceptTo)s does not have an order attribute.  "
                              "Please provide a value."),
                            edgarCode="rq-1201-Presentation-Order-Missing",
                            modelObject=elt,
                            xlinkFrom=elt.get(
                                "{http://www.w3.org/1999/xlink}from"),
                            xlinkTo=elt.get(
                                "{http://www.w3.org/1999/xlink}to"),
                            conceptFrom=arcFromConceptQname(elt),
                            conceptTo=arcToConceptQname(elt))
                    elif elt.localName == "calculationArc":
                        if not elt.get("order"):
                            val.modelXbrl.error(
                                ("EFM.6.14.01", "GFM.1.07.01"),
                                _("The calculation relationship from %(conceptFrom)s to %(conceptTo)s does not have an order attribute."
                                  ),
                                edgarCode=
                                "du-1401-Calculation-Relationship-Order-Missing",
                                modelObject=elt,
                                xlinkFrom=elt.get(
                                    "{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get(
                                    "{http://www.w3.org/1999/xlink}to"),
                                conceptFrom=arcFromConceptQname(elt),
                                conceptTo=arcToConceptQname(elt))
                        try:
                            weightAttr = elt.get("weight")
                            weight = float(weightAttr)
                            if not weight in (1, -1):
                                val.modelXbrl.error(
                                    ("EFM.6.14.02", "GFM.1.07.02"),
                                    _("Weight value %(weight)s on the calculation relationship from %(conceptFrom)s to %(conceptTo)s "
                                      "must be equal to 1 or to -1. Please recheck submission."
                                      ),
                                    edgarCode=
                                    "fs-1402-Calculation-Relationship-Weight-Not-Unitary",
                                    modelObject=elt,
                                    xlinkFrom=elt.get(
                                        "{http://www.w3.org/1999/xlink}from"),
                                    xlinkTo=elt.get(
                                        "{http://www.w3.org/1999/xlink}to"),
                                    conceptFrom=arcFromConceptQname(elt),
                                    conceptTo=arcToConceptQname(elt),
                                    weight=weightAttr)
                        except ValueError:
                            val.modelXbrl.error(
                                ("EFM.6.14.02", "GFM.1.07.02"),
                                _("Weight value %(weight)s on the calculation relationship from %(conceptFrom)s to %(conceptTo)s "
                                  "must be equal to 1 or to -1. Please recheck submission."
                                  ),
                                edgarCode=
                                "fs-1402-Calculation-Relationship-Weight-Not-Unitary",
                                modelObject=elt,
                                xlinkFrom=elt.get(
                                    "{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get(
                                    "{http://www.w3.org/1999/xlink}to"),
                                conceptFrom=arcFromConceptQname(elt),
                                conceptTo=arcToConceptQname(elt),
                                weight=weightAttr)
                    elif elt.localName == "definitionArc":
                        if not elt.get("order"):
                            val.modelXbrl.error(
                                ("EFM.6.16.01", "GFM.1.08.01"),
                                _("The Definition relationship from %(conceptFrom)s to %(conceptTo)s does not have an order attribute."
                                  ),
                                edgarCode=
                                "du-1601-Definition-Relationship-Order-Missing",
                                modelObject=elt,
                                xlinkFrom=elt.get(
                                    "{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get(
                                    "{http://www.w3.org/1999/xlink}to"),
                                conceptFrom=arcFromConceptQname(elt),
                                conceptTo=arcToConceptQname(elt))
Example #6
0
def checkDTSdocument(val, modelDocument, isFilingDocument):
    for hrefElt, _hrefedDoc, hrefId in modelDocument.hrefObjects:
        if hrefId:  #check scheme regardless of whether document loaded
            # check all xpointer schemes
            for scheme, _path in XmlUtil.xpointerSchemes(hrefId):
                if scheme == "element" and val.validateDisclosureSystem:
                    val.modelXbrl.error(
                        ("EFM.6.03.06", "GFM.1.01.03"),
                        _("Href %(elementHref)s may only have shorthand xpointers"
                          ),
                        modelObject=hrefElt,
                        elementHref=hrefElt.get(
                            "{http://www.w3.org/1999/xlink}href"))

    if not isFilingDocument:
        return  # not a filing's extension document

    if modelDocument.type == ModelDocument.Type.SCHEMA:
        if modelDocument.targetNamespace is not None and len(
                modelDocument.targetNamespace) > 85:
            l = len(modelDocument.targetNamespace.encode("utf-8"))
            if l > 255:
                val.modelXbrl.error(
                    "EFM.6.07.30",
                    _("Schema targetNamespace length (%(length)s) is over 255 bytes long in utf-8 %(targetNamespace)s"
                      ),
                    modelObject=modelDocument.xmlRootElement,
                    length=l,
                    targetNamespace=modelDocument.targetNamespace,
                    value=modelDocument.targetNamespace)

    if modelDocument.type in (ModelDocument.Type.SCHEMA,
                              ModelDocument.Type.LINKBASE):
        isSchema = modelDocument.type == ModelDocument.Type.SCHEMA
        if isSchema:
            for elt in modelDocument.xmlRootElement.iter(
                    tag="{http://www.w3.org/2001/XMLSchema}*"):
                if elt.namespaceURI == XbrlConst.xsd:
                    localName = elt.localName
                    if localName in {"element", "complexType", "simpleType"}:
                        name = elt.get("name")
                        if name and len(name) > 64:
                            l = len(name.encode("utf-8"))
                            if l > 200:
                                val.modelXbrl.error(
                                    "EFM.6.07.29",
                                    _("Schema %(element)s has a name length (%(length)s) over 200 bytes long in utf-8, %(name)s."
                                      ),
                                    modelObject=elt,
                                    element=localName,
                                    name=name,
                                    length=l)

    for elt in modelDocument.xmlRootElement.iter():
        if isinstance(elt, ModelObject):
            xlinkType = elt.get("{http://www.w3.org/1999/xlink}type")
            xlinkRole = elt.get("{http://www.w3.org/1999/xlink}role")
            if elt.namespaceURI == XbrlConst.link:
                # check schema roleTypes
                if elt.localName in ("roleType", "arcroleType"):
                    uriAttr = {
                        "roleType": "roleURI",
                        "arcroleType": "arcroleURI"
                    }[elt.localName]
                    roleURI = elt.get(uriAttr)
                    if len(roleURI) > 85:
                        l = len(roleURI.encode("utf-8"))
                        if l > 255:
                            val.modelXbrl.error(
                                "EFM.6.07.30",
                                _("Schema %(element)s %(attribute)s length (%(length)s) is over 255 bytes long in utf-8 %(roleURI)s"
                                  ),
                                modelObject=elt,
                                element=elt.qname,
                                attribute=uriAttr,
                                length=l,
                                roleURI=roleURI,
                                value=roleURI)

                if elt.localName == "arcroleRef":
                    refUri = elt.get("arcroleURI")
                    hrefAttr = elt.get("{http://www.w3.org/1999/xlink}href")
                    hrefUri, hrefId = UrlUtil.splitDecodeFragment(hrefAttr)
                    if hrefUri not in val.disclosureSystem.standardTaxonomiesDict:
                        val.modelXbrl.error(
                            ("EFM.6.09.06", "GFM.1.04.06"),
                            _("Arcrole %(refURI)s arcroleRef %(xlinkHref)s must be a standard taxonomy"
                              ),
                            modelObject=elt,
                            refURI=refUri,
                            xlinkHref=hrefUri)
            if modelDocument.type == ModelDocument.Type.INLINEXBRL and elt.namespaceURI in XbrlConst.ixbrlAll:
                if elt.localName == "footnote":
                    if val.validateGFM:
                        if elt.get("{http://www.w3.org/1999/xlink}arcrole"
                                   ) != XbrlConst.factFootnote:
                            # must be in a nonDisplay div
                            if not any(
                                    inlineDisplayNonePattern.search(
                                        e.get("style") or "")
                                    for e in XmlUtil.ancestors(
                                        elt, XbrlConst.xhtml, "div")):
                                val.modelXbrl.error(
                                    ("EFM.N/A", "GFM:1.10.16"),
                                    _("Inline XBRL footnote %(footnoteID)s must be in non-displayable div due to arcrole %(arcrole)s"
                                      ),
                                    modelObject=elt,
                                    footnoteID=elt.get("footnoteID"),
                                    arcrole=elt.get(
                                        "{http://www.w3.org/1999/xlink}arcrole"
                                    ))

                        if not elt.get(
                                "{http://www.w3.org/XML/1998/namespace}lang"):
                            val.modelXbrl.error(
                                ("EFM.N/A", "GFM:1.10.13"),
                                _("Inline XBRL footnote %(footnoteID)s is missing an xml:lang attribute"
                                  ),
                                modelObject=elt,
                                footnoteID=id)
            if xlinkType == "extended":
                if not xlinkRole or xlinkRole == "":
                    val.modelXbrl.error(("EFM.6.09.04", "GFM.1.04.04"),
                                        "%(element)s is missing an xlink:role",
                                        modelObject=elt,
                                        element=elt.qname)
                if not val.extendedElementName:
                    val.extendedElementName = elt.qname
                elif val.extendedElementName != elt.qname:
                    val.modelXbrl.error(
                        ("EFM.6.09.07", "GFM:1.04.07"),
                        _("Extended element %(element)s must be the same as %(element2)s"
                          ),
                        modelObject=elt,
                        element=elt.qname,
                        element2=val.extendedElementName)
            elif xlinkType == "resource":
                if not xlinkRole:
                    val.modelXbrl.error(
                        ("EFM.6.09.04", "GFM.1.04.04"),
                        _("%(element)s is missing an xlink:role"),
                        modelObject=elt,
                        element=elt.qname)
                elif not XbrlConst.isStandardRole(xlinkRole):
                    modelsRole = val.modelXbrl.roleTypes.get(xlinkRole)
                    if (modelsRole is None or len(modelsRole) == 0
                            or modelsRole[0].modelDocument.targetNamespace
                            not in val.disclosureSystem.standardTaxonomiesDict
                        ):
                        val.modelXbrl.error(
                            ("EFM.6.09.05", "GFM.1.04.05"),
                            _("Resource %(xlinkLabel)s role %(role)s is not a standard taxonomy role"
                              ),
                            modelObject=elt,
                            xlinkLabel=elt.get(
                                "{http://www.w3.org/1999/xlink}label"),
                            role=xlinkRole,
                            element=elt.qname,
                            roleDefinition=val.modelXbrl.roleTypeDefinition(
                                xlinkRole))
            elif xlinkType == "arc":
                if elt.get("priority") is not None:
                    priority = elt.get("priority")
                    try:
                        if int(priority) >= 10:
                            val.modelXbrl.error(
                                ("EFM.6.09.09", "GFM.1.04.08"),
                                _("Arc from %(xlinkFrom)s to %(xlinkTo)s priority %(priority)s must be less than 10"
                                  ),
                                modelObject=elt,
                                arcElement=elt.qname,
                                xlinkFrom=elt.get(
                                    "{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get(
                                    "{http://www.w3.org/1999/xlink}to"),
                                priority=priority)
                    except (ValueError):
                        val.modelXbrl.error(
                            ("EFM.6.09.09", "GFM.1.04.08"),
                            _("Arc from %(xlinkFrom)s to %(xlinkTo)s priority %(priority)s is not an integer"
                              ),
                            modelObject=elt,
                            arcElement=elt.qname,
                            xlinkFrom=elt.get(
                                "{http://www.w3.org/1999/xlink}from"),
                            xlinkTo=elt.get(
                                "{http://www.w3.org/1999/xlink}to"),
                            priority=priority)
                if elt.namespaceURI == XbrlConst.link:
                    if elt.localName == "presentationArc" and not elt.get(
                            "order"):
                        val.modelXbrl.error(
                            ("EFM.6.12.01", "GFM.1.06.01"),
                            _("PresentationArc from %(xlinkFrom)s to %(xlinkTo)s must have an order"
                              ),
                            modelObject=elt,
                            xlinkFrom=elt.get(
                                "{http://www.w3.org/1999/xlink}from"),
                            xlinkTo=elt.get(
                                "{http://www.w3.org/1999/xlink}to"),
                            conceptFrom=arcFromConceptQname(elt),
                            conceptTo=arcToConceptQname(elt))
                    elif elt.localName == "calculationArc":
                        if not elt.get("order"):
                            val.modelXbrl.error(
                                ("EFM.6.14.01", "GFM.1.07.01"),
                                _("CalculationArc from %(xlinkFrom)s to %(xlinkTo)s must have an order"
                                  ),
                                modelObject=elt,
                                xlinkFrom=elt.get(
                                    "{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get(
                                    "{http://www.w3.org/1999/xlink}to"),
                                conceptFrom=arcFromConceptQname(elt),
                                conceptTo=arcToConceptQname(elt))
                        try:
                            weightAttr = elt.get("weight")
                            weight = float(weightAttr)
                            if not weight in (1, -1):
                                val.modelXbrl.error(
                                    ("EFM.6.14.02", "GFM.1.07.02"),
                                    _("CalculationArc from %(xlinkFrom)s to %(xlinkTo)s weight %(weight)s must be 1 or -1"
                                      ),
                                    modelObject=elt,
                                    xlinkFrom=elt.get(
                                        "{http://www.w3.org/1999/xlink}from"),
                                    xlinkTo=elt.get(
                                        "{http://www.w3.org/1999/xlink}to"),
                                    conceptFrom=arcFromConceptQname(elt),
                                    conceptTo=arcToConceptQname(elt),
                                    weight=weightAttr)
                        except ValueError:
                            val.modelXbrl.error(
                                ("EFM.6.14.02", "GFM.1.07.02"),
                                _("CalculationArc from %(xlinkFrom)s to %(xlinkTo)s must have an weight (value error in \"%(weight)s\")"
                                  ),
                                modelObject=elt,
                                xlinkFrom=elt.get(
                                    "{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get(
                                    "{http://www.w3.org/1999/xlink}to"),
                                conceptFrom=arcFromConceptQname(elt),
                                conceptTo=arcToConceptQname(elt),
                                weight=weightAttr)
                    elif elt.localName == "definitionArc":
                        if not elt.get("order"):
                            val.modelXbrl.error(
                                ("EFM.6.16.01", "GFM.1.08.01"),
                                _("DefinitionArc from %(xlinkFrom)s to %(xlinkTo)s must have an order"
                                  ),
                                modelObject=elt,
                                xlinkFrom=elt.get(
                                    "{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get(
                                    "{http://www.w3.org/1999/xlink}to"),
                                conceptFrom=arcFromConceptQname(elt),
                                conceptTo=arcToConceptQname(elt))
Example #7
0
def checkDTSdocument(val, modelDocument, isFilingDocument):
    for hrefElt, _hrefedDoc, hrefId in modelDocument.hrefObjects:
        if hrefId:  #check scheme regardless of whether document loaded 
            # check all xpointer schemes
            for scheme, _path in XmlUtil.xpointerSchemes(hrefId):
                if scheme == "element" and val.validateDisclosureSystem:
                    val.modelXbrl.error(("EFM.6.03.06", "GFM.1.01.03"),
                        _("Href %(elementHref)s may only have shorthand xpointers"),
                        modelObject=hrefElt, 
                        elementHref=hrefElt.get("{http://www.w3.org/1999/xlink}href"))
    
    if not isFilingDocument:
        return  # not a filing's extension document
    
    if modelDocument.type == ModelDocument.Type.SCHEMA:
        if modelDocument.targetNamespace is not None and len(modelDocument.targetNamespace) > 85:
            l = len(modelDocument.targetNamespace.encode("utf-8"))
            if l > 255:
                val.modelXbrl.error("EFM.6.07.30",
                    _("Schema targetNamespace length (%(length)s) is over 255 bytes long in utf-8 %(targetNamespace)s"),
                    modelObject=modelDocument.xmlRootElement, length=l, targetNamespace=modelDocument.targetNamespace, value=modelDocument.targetNamespace)

    if modelDocument.type in (ModelDocument.Type.SCHEMA, ModelDocument.Type.LINKBASE):
        isSchema = modelDocument.type == ModelDocument.Type.SCHEMA
        if isSchema:
            for elt in modelDocument.xmlRootElement.iter(tag="{http://www.w3.org/2001/XMLSchema}*"):
                if elt.namespaceURI == XbrlConst.xsd:
                    localName = elt.localName
                    if localName in {"element", "complexType", "simpleType"}:
                        name = elt.get("name")
                        if name and len(name) > 64:
                            l = len(name.encode("utf-8"))
                            if l > 200:
                                val.modelXbrl.error("EFM.6.07.29",
                                    _("Schema %(element)s has a name length (%(length)s) over 200 bytes long in utf-8, %(name)s."),
                                    modelObject=elt, element=localName, name=name, length=l)
    
    for elt in modelDocument.xmlRootElement.iter():
        if isinstance(elt, ModelObject):
            xlinkType = elt.get("{http://www.w3.org/1999/xlink}type")
            xlinkRole = elt.get("{http://www.w3.org/1999/xlink}role")
            if elt.namespaceURI == XbrlConst.link:
                # check schema roleTypes        
                if elt.localName in ("roleType","arcroleType"):
                    uriAttr = {"roleType":"roleURI", "arcroleType":"arcroleURI"}[elt.localName]
                    roleURI = elt.get(uriAttr)
                    if len(roleURI) > 85:
                        l = len(roleURI.encode("utf-8"))
                        if l > 255:
                            val.modelXbrl.error("EFM.6.07.30",
                                _("Schema %(element)s %(attribute)s length (%(length)s) is over 255 bytes long in utf-8 %(roleURI)s"),
                                modelObject=elt, element=elt.qname, attribute=uriAttr, length=l, roleURI=roleURI, value=roleURI)
    
                if elt.localName == "arcroleRef":
                    refUri = elt.get("arcroleURI")
                    hrefAttr = elt.get("{http://www.w3.org/1999/xlink}href")
                    hrefUri, hrefId = UrlUtil.splitDecodeFragment(hrefAttr)
                    if hrefUri not in val.disclosureSystem.standardTaxonomiesDict:
                        val.modelXbrl.error(("EFM.6.09.06", "GFM.1.04.06"),
                            _("Arcrole %(refURI)s arcroleRef %(xlinkHref)s must be a standard taxonomy"),
                            modelObject=elt, refURI=refUri, xlinkHref=hrefUri)
            if modelDocument.type == ModelDocument.Type.INLINEXBRL and elt.namespaceURI in XbrlConst.ixbrlAll: 
                if elt.localName == "footnote":
                    if val.validateGFM:
                        if elt.get("{http://www.w3.org/1999/xlink}arcrole") != XbrlConst.factFootnote:
                            # must be in a nonDisplay div
                            if not any(inlineDisplayNonePattern.search(e.get("style") or "")
                                       for e in XmlUtil.ancestors(elt, XbrlConst.xhtml, "div")):
                                val.modelXbrl.error(("EFM.N/A", "GFM:1.10.16"),
                                    _("Inline XBRL footnote %(footnoteID)s must be in non-displayable div due to arcrole %(arcrole)s"),
                                    modelObject=elt, footnoteID=elt.get("footnoteID"), 
                                    arcrole=elt.get("{http://www.w3.org/1999/xlink}arcrole"))
                            
                        if not elt.get("{http://www.w3.org/XML/1998/namespace}lang"):
                            val.modelXbrl.error(("EFM.N/A", "GFM:1.10.13"),
                                _("Inline XBRL footnote %(footnoteID)s is missing an xml:lang attribute"),
                                modelObject=elt, footnoteID=id)
            if xlinkType == "extended":
                if not xlinkRole or xlinkRole == "":
                    val.modelXbrl.error(("EFM.6.09.04", "GFM.1.04.04"),
                        "%(element)s is missing an xlink:role",
                        modelObject=elt, element=elt.qname)
                if not val.extendedElementName:
                    val.extendedElementName = elt.qname
                elif val.extendedElementName != elt.qname:
                    val.modelXbrl.error(("EFM.6.09.07", "GFM:1.04.07"),
                        _("Extended element %(element)s must be the same as %(element2)s"),
                        modelObject=elt, element=elt.qname, element2=val.extendedElementName)
            elif xlinkType == "resource":
                if not xlinkRole:
                    val.modelXbrl.error(("EFM.6.09.04", "GFM.1.04.04"),
                        _("%(element)s is missing an xlink:role"),
                        modelObject=elt, element=elt.qname)
                elif not XbrlConst.isStandardRole(xlinkRole):
                    modelsRole = val.modelXbrl.roleTypes.get(xlinkRole)
                    if (modelsRole is None or len(modelsRole) == 0 or 
                        modelsRole[0].modelDocument.targetNamespace not in val.disclosureSystem.standardTaxonomiesDict):
                        val.modelXbrl.error(("EFM.6.09.05", "GFM.1.04.05"),
                            _("Resource %(xlinkLabel)s role %(role)s is not a standard taxonomy role"),
                            modelObject=elt, xlinkLabel=elt.get("{http://www.w3.org/1999/xlink}label"), role=xlinkRole, element=elt.qname,
                            roleDefinition=val.modelXbrl.roleTypeDefinition(xlinkRole))
            elif xlinkType == "arc":
                if elt.get("priority") is not None:
                    priority = elt.get("priority")
                    try:
                        if int(priority) >= 10:
                            val.modelXbrl.error(("EFM.6.09.09", "GFM.1.04.08"),
                                _("Arc from %(xlinkFrom)s to %(xlinkTo)s priority %(priority)s must be less than 10"),
                                modelObject=elt, 
                                arcElement=elt.qname,
                                xlinkFrom=elt.get("{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get("{http://www.w3.org/1999/xlink}to"),
                                priority=priority)
                    except (ValueError) :
                        val.modelXbrl.error(("EFM.6.09.09", "GFM.1.04.08"),
                            _("Arc from %(xlinkFrom)s to %(xlinkTo)s priority %(priority)s is not an integer"),
                            modelObject=elt, 
                            arcElement=elt.qname,
                            xlinkFrom=elt.get("{http://www.w3.org/1999/xlink}from"),
                            xlinkTo=elt.get("{http://www.w3.org/1999/xlink}to"),
                            priority=priority)
                if elt.namespaceURI == XbrlConst.link:
                    if elt.localName == "presentationArc" and not elt.get("order"):
                        val.modelXbrl.error(("EFM.6.12.01", "GFM.1.06.01"),
                            _("PresentationArc from %(xlinkFrom)s to %(xlinkTo)s must have an order"),
                            modelObject=elt, 
                            xlinkFrom=elt.get("{http://www.w3.org/1999/xlink}from"),
                            xlinkTo=elt.get("{http://www.w3.org/1999/xlink}to"),
                            conceptFrom=arcFromConceptQname(elt),
                            conceptTo=arcToConceptQname(elt))
                    elif elt.localName == "calculationArc":
                        if not elt.get("order"):
                            val.modelXbrl.error(("EFM.6.14.01", "GFM.1.07.01"),
                                _("CalculationArc from %(xlinkFrom)s to %(xlinkTo)s must have an order"),
                                modelObject=elt, 
                                xlinkFrom=elt.get("{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get("{http://www.w3.org/1999/xlink}to"),
                                conceptFrom=arcFromConceptQname(elt),
                                conceptTo=arcToConceptQname(elt))
                        try:
                            weightAttr = elt.get("weight")
                            weight = float(weightAttr)
                            if not weight in (1, -1):
                                val.modelXbrl.error(("EFM.6.14.02", "GFM.1.07.02"),
                                    _("CalculationArc from %(xlinkFrom)s to %(xlinkTo)s weight %(weight)s must be 1 or -1"),
                                    modelObject=elt, 
                                    xlinkFrom=elt.get("{http://www.w3.org/1999/xlink}from"),
                                    xlinkTo=elt.get("{http://www.w3.org/1999/xlink}to"),
                                    conceptFrom=arcFromConceptQname(elt),
                                    conceptTo=arcToConceptQname(elt),
                                    weight=weightAttr)
                        except ValueError:
                            val.modelXbrl.error(("EFM.6.14.02", "GFM.1.07.02"),
                                _("CalculationArc from %(xlinkFrom)s to %(xlinkTo)s must have an weight (value error in \"%(weight)s\")"),
                                modelObject=elt, 
                                xlinkFrom=elt.get("{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get("{http://www.w3.org/1999/xlink}to"),
                                conceptFrom=arcFromConceptQname(elt),
                                conceptTo=arcToConceptQname(elt),
                                weight=weightAttr)
                    elif elt.localName == "definitionArc":
                        if not elt.get("order"):
                            val.modelXbrl.error(("EFM.6.16.01", "GFM.1.08.01"),
                                _("DefinitionArc from %(xlinkFrom)s to %(xlinkTo)s must have an order"),
                                modelObject=elt, 
                                xlinkFrom=elt.get("{http://www.w3.org/1999/xlink}from"),
                                xlinkTo=elt.get("{http://www.w3.org/1999/xlink}to"),
                                conceptFrom=arcFromConceptQname(elt),
                                conceptTo=arcToConceptQname(elt))