Example #1
0
def generateInfoset(dts, infosetFile):
    if dts.fileSource.isArchive:
        return
    import os, io
    from arelle import XmlUtil, XbrlConst
    from arelle.ValidateXbrlCalcs import inferredPrecision, inferredDecimals            
    
    XmlUtil.setXmlns(dts.modelDocument, "ptv", "http://www.xbrl.org/2003/ptv")
    
    numFacts = 0
    
    for fact in dts.facts:
        try:
            if fact.concept.periodType:
                fact.set("{http://www.xbrl.org/2003/ptv}periodType", fact.concept.periodType)
            if fact.concept.balance:
                fact.set("{http://www.xbrl.org/2003/ptv}balance", fact.concept.balance)
            if fact.isNumeric and not fact.isNil:
                fact.set("{http://www.xbrl.org/2003/ptv}decimals", str(inferredDecimals(fact)))
                fact.set("{http://www.xbrl.org/2003/ptv}precision", str(inferredPrecision(fact)))
            numFacts += 1
        except Exception as err:
            dts.error("saveInfoset.exception",
                     _("Facts exception %(fact)s %(value)s %(error)s."),
                     modelObject=fact, fact=fact.qname, value=fact.effectiveValue, error = err)

    fh = open(infosetFile, "w", encoding="utf-8")
    XmlUtil.writexml(fh, dts.modelDocument.xmlDocument, encoding="utf-8")
    fh.close()
    
    dts.info("info:saveInfoset",
             _("Infoset of %(entryFile)s has %(numberOfFacts)s facts in infoset file %(infosetOutputFile)s."),
             modelObject=dts,
             entryFile=dts.uri, numberOfFacts=numFacts, infosetOutputFile=infosetFile)
Example #2
0
 def lbTreeWalk(lbType, parentElt, lbList, roleRefs, locs=None, fromPrefix=None, fromName=None):
     order = 1.0
     for toPrefix, toName, rel, list in lbList:
         if rel == "_ELR_":
             role = "unspecified"
             if toPrefix and toPrefix.startswith("http://"): # have a role specified
                 role = toPrefix
             elif toName: #may be a definition
                 for linkroleUri, modelRoleTypes in dts.roleTypes.items():
                     definition = modelRoleTypes[0].definition
                     if toName == definition:
                         role = linkroleUri
                         break
             if role != XbrlConst.defaultLinkRole and role in dts.roleTypes: # add roleRef
                 roleType = modelRoleTypes[0]
                 roleRef = ("roleRef", role, roleType.modelDocument.uri + "#" + roleType.id)
                 roleRefs.add(roleRef)
             linkElt = XmlUtil.addChild(parentElt, 
                                        XbrlConst.link, lbType + "Link",
                                        attributes=(("{http://www.w3.org/1999/xlink}type", "extended"),
                                                    ("{http://www.w3.org/1999/xlink}role", role)))
             locs = set()
             lbTreeWalk(lbType, linkElt, list, roleRefs, locs)
         else:
             toHref = extensionHref(toPrefix, toName)
             toLabel = toPrefix + "_" + toName
             if toHref not in locs:
                 XmlUtil.addChild(parentElt,
                                  XbrlConst.link, "loc",
                                  attributes=(("{http://www.w3.org/1999/xlink}type", "locator"),
                                              ("{http://www.w3.org/1999/xlink}href", toHref),
                                              ("{http://www.w3.org/1999/xlink}label", toLabel)))        
                 locs.add(toHref)
             if rel != "_root_":
                 fromLabel = fromPrefix + "_" + fromName
                 if lbType == "calculation":
                     otherAttrs = ( ("weight", list), )
                 else:
                     otherAttrs = ( )
                 if rel == "_dimensions_":  # pick proper consecutive arcrole
                     fromConcept = hrefConcept(fromPrefix, fromName)
                     toConcept = hrefConcept(toPrefix, toName)
                     if toConcept is not None and toConcept.isHypercubeItem:
                         rel = XbrlConst.all
                     elif toConcept is not None and toConcept.isDimensionItem:
                         rel = XbrlConst.hypercubeDimension
                     elif fromConcept is not None and fromConcept.isDimensionItem:
                         rel = XbrlConst.dimensionDomain
                     else:
                         rel = XbrlConst.domainMember
                 XmlUtil.addChild(parentElt,
                                  XbrlConst.link, lbType + "Arc",
                                  attributes=(("{http://www.w3.org/1999/xlink}type", "arc"),
                                              ("{http://www.w3.org/1999/xlink}arcrole", rel),
                                              ("{http://www.w3.org/1999/xlink}from", fromLabel), 
                                              ("{http://www.w3.org/1999/xlink}to", toLabel), 
                                              ("order", order)) + otherAttrs )
                 order += 1.0
             if lbType != "calculation" or rel == "_root_":
                 lbTreeWalk(lbType, parentElt, list, roleRefs, locs, toPrefix, toName)
Example #3
0
def factAspectValue(fact, aspect, view=False):
    if aspect == Aspect.LOCATION:
        parentQname = fact.getparent().qname
        if parentQname == XbrlConst.qnXbrliXbrl: # not tuple
            return NONE
        return parentQname # tuple
    elif aspect == Aspect.CONCEPT:
        return fact.qname
    elif fact.isTuple or fact.context is None:
        return NONE     #subsequent aspects don't exist for tuples
    elif aspect == Aspect.UNIT:
        if fact.unit is None:
            return NONE
        measures = fact.unit.measures
        if measures[1]:
            return "{0} / {1}".format(' '.join(str(m) for m in measures[0]),
                                      ' '.join(str(m) for m in measures[1]))
        else:
            return ' '.join(str(m) for m in measures[0])
    else:
        context = fact.context
        if aspect == Aspect.PERIOD:
            return ("forever" if context.isForeverPeriod else
                XmlUtil.dateunionValue(context.instantDatetime, subtractOneDay=True) if context.isInstantPeriod else
                XmlUtil.dateunionValue(context.startDatetime) + "-" + XmlUtil.dateunionValue(context.endDatetime, subtractOneDay=True))
        elif aspect == Aspect.ENTITY_IDENTIFIER:
            if view:
                return context.entityIdentifier[1]
            else:
                return context.entityIdentifier  # (scheme, identifier)
        elif aspect in (Aspect.COMPLETE_SEGMENT, Aspect.COMPLETE_SCENARIO,
                        Aspect.NON_XDT_SEGMENT, Aspect.NON_XDT_SCENARIO):
            return ''.join(XmlUtil.xmlstring(elt, stripXmlns=True, prettyPrint=True)
                           for elt in context.nonDimValues(aspect))
Example #4
0
 def reference(self):
     efmNameElts = XmlUtil.children(self.getparent(), None, "name")
     for efmNameElt in efmNameElts:
         if efmNameElt is not None and efmNameElt.text.startswith("EDGAR"):
             return efmNameElt.text
     referenceElement = XmlUtil.descendant(self, None, "reference")
     if referenceElement is not None:  # formula test suite
         return "{0}#{1}".format(
             referenceElement.get("specification"),
             referenceElement.get("id"))
     referenceElement = XmlUtil.descendant(self, None,
                                           "documentationReference")
     if referenceElement is not None:  # w3c test suite
         return referenceElement.get("{http://www.w3.org/1999/xlink}href")
     descriptionElement = XmlUtil.descendant(self, None, "description")
     if descriptionElement is not None and descriptionElement.get(
             "reference"):
         return descriptionElement.get("reference")  # xdt test suite
     if self.getparent().get("description"):
         return self.getparent().get(
             "description")  # base spec 2.1 test suite
     functRegistryRefElt = XmlUtil.descendant(self.getparent(), None,
                                              "reference")
     if functRegistryRefElt is not None:  # function registry
         return functRegistryRefElt.get(
             "{http://www.w3.org/1999/xlink}href")
     return None
Example #5
0
 def expected(self):
     if self.localName == "testcase":
         return self.document.basename[:4]   #starts with PASS or FAIL
     errorElement = XmlUtil.descendant(self, None, "error")
     if errorElement is not None:
         return ModelValue.qname(errorElement, XmlUtil.text(errorElement))
     resultElement = XmlUtil.descendant(self, None, "result")
     if resultElement is not None:
         expected = resultElement.get("expected")
         if expected:
             return expected
         for assertElement in XmlUtil.children(resultElement, None, "assert"):
             num = assertElement.get("num")
             if len(num) == 5:
                 return "EFM.{0}.{1}.{2}".format(num[0],num[1:3],num[3:6])
         asserTests = {}
         for atElt in XmlUtil.children(resultElement, None, "assertionTests"):
             try:
                 asserTests[atElt.get("assertionID")] = (_INT(atElt.get("countSatisfied")),_INT(atElt.get("countNotSatisfied")))
             except ValueError:
                 pass
         if asserTests:
             return asserTests
     elif self.get("result"):
         return self.get("result")
             
     return None
Example #6
0
 def explicitDims(self):
     return {
         (self.prefixedNameQname(e.get("dimension")), self.prefixedNameQname(XmlUtil.text(qn)))
         for e in XmlUtil.children(self, XbrlConst.formula, "explicitDimension")
         for m in XmlUtil.children(e, XbrlConst.formula, "member")
         for qn in XmlUtil.children(m, XbrlConst.formula, "qname")
     }
 def primaryItemQname(self):
     conceptRule = XmlUtil.child(self, XbrlConst.formula, "concept")
     if conceptRule is not None:
         qnameElt = XmlUtil.child(conceptRule, XbrlConst.formula, "qname")
         if qnameElt is not None:
             return qname(qnameElt, qnameElt.text)
     return None
Example #8
0
 def file(self,filepath):
     archiveFileSource = self.fileSourceContainingFilepath(filepath)
     if archiveFileSource is not None:
         if filepath.startswith(archiveFileSource.basefile):
             archiveFileName = filepath[len(archiveFileSource.basefile) + 1:]
         else: # filepath.startswith(self.baseurl)
             archiveFileName = filepath[len(archiveFileSource.baseurl) + 1:]
         if archiveFileSource.isZip:
             b = archiveFileSource.fs.read(archiveFileName.replace("\\","/"))
             encoding = XmlUtil.encoding(b)
             return (io.TextIOWrapper(
                     io.BytesIO(b), 
                     encoding=encoding), encoding)
         elif archiveFileSource.isXfd:
             for data in archiveFileSource.xfdDocument.iter(tag="data"):
                 outfn = data.findtext("filename")
                 if outfn == archiveFileName:
                     b64data = data.findtext("mimedata")
                     if b64data:
                         # convert to bytes
                         #byteData = []
                         #for c in b64data:
                         #    byteData.append(ord(c))
                         b = base64.b64decode(b64data.encode("latin-1"))
                         # remove BOM codes if present
                         if len(b) > 3 and b[0] == 239 and b[1] == 187 and b[2] == 191:
                             start = 3;
                             length = len(b) - 3;
                             b = b[start:start + length]
                         else:
                             start = 0;
                             length = len(b);
                         # pass back as ascii
                         #str = ""
                         #for bChar in b[start:start + length]:
                         #    str += chr( bChar )
                         #return str
                         return (io.TextIOWrapper(
                             io.BytesIO(b), 
                             encoding=XmlUtil.encoding(b)), "latin-1")
             return (None,None)
     # check encoding
     with open(filepath, 'rb') as fb:
         hdrBytes = fb.peek(512)
         encoding = XmlUtil.encoding(hdrBytes)
         if encoding.lower() in ('utf-8','utf8'):
             text = None
         else:
             text = fb.read().decode(encoding)
         # allow filepath to close
     # this may not be needed for Mac or Linux, needs confirmation!!!
     if text is None:  # ok to read as utf-8
         return (open(filepath, 'rt', encoding='utf-8'), encoding)
     else:
         # strip XML declaration
         xmlDeclarationMatch = XMLdeclaration.search(text)
         if xmlDeclarationMatch: # remove it for lxml
             start,end = xmlDeclarationMatch.span()
             text = text[0:start] + text[end:]
         return (io.StringIO(initial_value=text), encoding)
Example #9
0
 def generateAxis(newLinkElt, newAxisParentElt, srcAxisElt, axisMbrRelSet, visited):
     for rel in axisMbrRelSet.fromModelObject(srcAxisElt):
         tgtAxisElt = rel.toModelObject
         if isinstance(tgtAxisElt, ModelEuAxisCoord) and tgtAxisElt not in visited:
             visited.add(tgtAxisElt)
             newAxisElt = etree.SubElement(newLinkElt, "{http://xbrl.org/2011/table}ruleAxis")
             copyAttrs(tgtAxisElt, newAxisElt, ("id", 
                                                "abstract",
                                                "{http://www.w3.org/1999/xlink}type",
                                                "{http://www.w3.org/1999/xlink}label"))
             if tgtAxisElt.primaryItemQname:
                 newRuleElt = etree.SubElement(newAxisElt, "{http://xbrl.org/2008/formula}concept")
                 newQnameElt = etree.SubElement(newRuleElt, "{http://xbrl.org/2008/formula}qname")
                 newQnameElt.text = XmlUtil.addQnameValue(docObj, tgtAxisElt.primaryItemQname)
             for dimQname, memQname in tgtAxisElt.explicitDims:
                 newRuleElt = etree.SubElement(newAxisElt, "{http://xbrl.org/2008/formula}explicitDimension")
                 newRuleElt.set("dimension", XmlUtil.addQnameValue(docObj, dimQname))
                 newMbrElt = etree.SubElement(newRuleElt, "{http://xbrl.org/2008/formula}member")
                 newQnameElt = etree.SubElement(newMbrElt, "{http://xbrl.org/2008/formula}qname")
                 newQnameElt.text = XmlUtil.addQnameValue(docObj, memQname)
             newArcElt = etree.SubElement(newLinkElt, "{http://xbrl.org/2011/table}axisArc")
             copyAttrs(rel, newArcElt, ("id", 
                                        "{http://www.w3.org/1999/xlink}type",
                                        "{http://www.w3.org/1999/xlink}from",
                                        "{http://www.w3.org/1999/xlink}to",
                                        "order"))
             newArcElt.set("{http://www.w3.org/1999/xlink}arcrole", XbrlConst.tableAxisSubtree)
             generateAxis(newLinkElt, newAxisElt, tgtAxisElt, axisMbrRelSet, visited)
             visited.discard(tgtAxisElt)
Example #10
0
def _durationFunction(node, sphinxContext, args):
    hasArg(node, sphinxContext, args, 1)
    startArg = args[0]
    if isinstance(startArg, str):
        startDateTime = Period(None, XmlUtil.datetimeValue(startArg, none=NONE))
    elif isinstance(startArg, datetime.datetime):
        startDateTime = startArg
    elif isinstance(arg, datetime.date):
        startDateTime = datetime.date(startArg.year, startArg.month, startArg.day)
    endArg = args[1]
    if isinstance(endArg, str):
        endDateTime = Period(None, XmlUtil.datetimeValue(startArg, addOneDay=True, none=NONE))
    elif isinstance(endArg, datetime.datetime):
        endDateTime = endArg
    elif isinstance(endArg, datetime.date):
        endDateTime = datetime.date(endArg.year, endArg.month, endArg.day) + datetime.timedelta(1)
    if startDateTime and endDateTime:
        return Period(startDateTime, endDateTime)
    raise SphinxException(
        node,
        "sphinx.functionArgumentsMismatch",
        _("Function %(name)s requires two argument that are a date or datetime string or value: %(start)s and %(end)s"),
        name=node.name,
        start=startArg,
        end=endArg,
    )
Example #11
0
 def pubDate(self):
     try:
         return self._pubDate
     except AttributeError:
         from arelle.UrlUtil import parseRfcDatetime
         self._pubDate = parseRfcDatetime(XmlUtil.text(XmlUtil.descendant(self, None, "pubDate")))
         return self._pubDate
Example #12
0
 def startDatetime(self):
     """(datetime) -- startDate attribute"""
     try:
         return self._startDatetime
     except AttributeError:
         self._startDatetime = XmlUtil.datetimeValue(XmlUtil.child(self.period, XbrlConst.xbrli, "startDate"))
         return self._startDatetime
Example #13
0
 def instantDatetime(self):
     """(datetime) -- instant attribute, with adjustment to end-of-day midnight as needed"""
     try:
         return self._instantDatetime
     except AttributeError:
         self._instantDatetime = XmlUtil.datetimeValue(XmlUtil.child(self.period, XbrlConst.xbrli, "instant"), addOneDay=True)
         return self._instantDatetime
Example #14
0
 def __init__(self, savedOptions=None, xbrlInstance=None):
     self.entityIdentScheme = ""
     self.entityIdentValue = ""
     self.startDate = ""  # use string  values so structure can be json-saved
     self.endDate = ""
     self.monetaryUnit = ""
     self.monetaryDecimals = ""
     self.nonMonetaryDecimals = ""
     if savedOptions is not None:
         self.__dict__.update(savedOptions)
     elif xbrlInstance is not None:
         for fact in xbrlInstance.facts:
             cntx = fact.context
             unit = fact.unit
             if fact.isItem and cntx is not None:
                 if not self.entityIdentScheme:
                     self.entityIdentScheme, self.entityIdentValue = cntx.entityIdentifier
                 if not self.startDate and cntx.isStartEndPeriod:
                     self.startDate = XmlUtil.dateunionValue(cntx.startDatetime)
                 if not self.startDate and (cntx.isStartEndPeriod or cntx.isInstantPeriod):
                     self.endDate = XmlUtil.dateunionValue(cntx.endDatetime, subtractOneDay=True)
                 if fact.isNumeric and unit is not None:
                     if fact.concept.isMonetary:
                         if not self.monetaryUnit and unit.measures[0] and unit.measures[0][0].namespaceURI == XbrlConst.iso4217:
                             self.monetaryUnit = unit.measures[0][0].localName
                         if not self.monetaryDecimals:
                             self.monetaryDecimals = fact.decimals
                     elif not self.nonMonetaryDecimals:
                         self.nonMonetaryDecimals = fact.decimals
             if self.entityIdentScheme and self.startDate and self.monetaryUnit and self.monetaryDecimals and self.nonMonetaryDecimals:
                 break 
Example #15
0
 def resultTableUri(self):
     result = XmlUtil.descendant(self, None, "result")
     if result is not None:
         child = XmlUtil.child(result, None, "table")
         if child is not None:
             return os.path.join(self.modelDocument.outpath, XmlUtil.text(child))
     return None    
 def cfcnTest(self):
     # tuple of (expression, element holding the expression)
     try:
         return self._cfcnTest
     except AttributeError:
         self._cfcnTest = None
         if self.localName == "test-case":  # xpath testcase
             outputFileElement = XmlUtil.descendant(self, None, "output-file")
             if outputFileElement is not None and outputFileElement.get("compare") == "Text":
                 filepath = (
                     self.modelDocument.filepathdir
                     + "/"
                     + "ExpectedTestResults/"
                     + self.get("FilePath")
                     + outputFileElement.text
                 )
                 if os.sep != "/":
                     filepath = filepath.replace("/", os.sep)
                 with io.open(filepath, "rt", encoding="utf-8") as f:
                     self._cfcnTest = ("xs:string($result) eq '{0}'".format(f.read()), self)
         else:
             testElement = XmlUtil.descendant(self, XbrlConst.cfcn, "test")
             if testElement is not None:
                 self._cfcnTest = (XmlUtil.innerText(testElement), testElement)
             elif self.namespaceURI == "http://xbrl.org/2011/conformance-rendering/transforms":
                 output = self.get("output")
                 if output:
                     self._cfcnTest = ("$result eq '{0}'".format(output.replace("'", "''")), self)
         return self._cfcnTest
Example #17
0
 def resultIsTable(self):
     result = XmlUtil.descendant(self, None, "result")
     if result is not None :
         child = XmlUtil.child(result, None, "table")
         if child is not None and XmlUtil.text(child).endswith(".xml"):
             return True
     return False
 def cfcnCall(self):
     # tuple of (expression, element holding the expression)
     try:
         return self._cfcnCall
     except AttributeError:
         self._cfcnCall = None
         if self.localName == "test-case":  # xpath testcase
             queryElement = XmlUtil.descendant(self, None, "query")
             if queryElement is not None:
                 filepath = (
                     self.modelDocument.filepathdir
                     + "/"
                     + "Queries/XQuery/"
                     + self.get("FilePath")
                     + queryElement.get("name")
                     + ".xq"
                 )
                 if os.sep != "/":
                     filepath = filepath.replace("/", os.sep)
                 with io.open(filepath, "rt", encoding="utf-8") as f:
                     self._cfcnCall = (f.read(), self)
         else:
             for callElement in XmlUtil.descendants(self, XbrlConst.cfcn, "call"):
                 self._cfcnCall = (XmlUtil.innerText(callElement), callElement)
                 break
         if self._cfcnCall is None and self.namespaceURI == "http://xbrl.org/2011/conformance-rendering/transforms":
             name = self.getparent().get("name")
             input = self.get("input")
             if name and input:
                 self._cfcnCall = ("{0}('{1}')".format(name, input.replace("'", "''")), self)
         return self._cfcnCall
def generateInstanceInfoset(dts, instanceInfosetFile):
    if dts.fileSource.isArchive:
        return
    import os, io
    from arelle import XmlUtil, XbrlConst
    from arelle.ValidateXbrlCalcs import inferredPrecision, inferredDecimals            
    
    XmlUtil.setXmlns(dts.modelDocument, u"ptv", u"http://www.xbrl.org/2003/ptv")
    
    numFacts = 0
    
    for fact in dts.facts:
        try:
            if fact.concept.periodType:
                fact.set(u"{http://www.xbrl.org/2003/ptv}periodType", fact.concept.periodType)
            if fact.concept.balance:
                fact.set(u"{http://www.xbrl.org/2003/ptv}balance", fact.concept.balance)
            if fact.isNumeric and not fact.isNil:
                fact.set(u"{http://www.xbrl.org/2003/ptv}decimals", unicode(inferredDecimals(fact)))
                fact.set(u"{http://www.xbrl.org/2003/ptv}precision", unicode(inferredPrecision(fact)))
            numFacts += 1
        except Exception, err:
            dts.error(u"saveInfoset.exception",
                     _(u"Facts exception %(fact)s %(value)s %(error)s."),
                     modelObject=fact, fact=fact.qname, value=fact.effectiveValue, error = err)
Example #20
0
 def close(self, noWrite=False):
     if self.type == CSV:
         if not isinstance(self.outfile, FileNamedStringIO):
             self.csvFile.close()
     elif not noWrite:
         fileType = TYPENAMES[self.type]
         try:
             from arelle import XmlUtil
             if isinstance(self.outfile, FileNamedStringIO):
                 fh = self.outfile
             else:
                 fh = open(self.outfile, "w", encoding="utf-8")
             if self.type == JSON:
                 fh.write(json.dumps(self.jsonObject, ensure_ascii=False))
             else:
                 XmlUtil.writexml(fh, self.xmlDoc, encoding="utf-8",
                                  xmlcharrefreplace= (self.type == HTML) )
             if not isinstance(self.outfile, FileNamedStringIO):
                 fh.close()
             self.modelXbrl.info("info", _("Saved output %(type)s to %(file)s"), file=self.outfile, type=fileType)
         except (IOError, EnvironmentError) as err:
             self.modelXbrl.exception("arelle:htmlIOError", _("Failed to save output %(type)s to %(file)s: \s%(error)s"), file=self.outfile, type=fileType, error=err)
     self.modelXbrl = None
     if self.type == HTML:
         self.tblElt = None
     elif self.type == XML:
         self.docEltLevels = None
     self.__dict__.clear() # dereference everything after closing document
Example #21
0
 def saveInstance(self, overrideFilepath=None):
     """Saves current instance document file.
     
     :param overrideFilepath: specify to override saving in instance's modelDocument.filepath
     """
     with open( (overrideFilepath or self.modelDocument.filepath), "w", encoding='utf-8') as fh:
         XmlUtil.writexml(fh, self.modelDocument.xmlDocument, encoding="utf-8")
Example #22
0
 def stepAxis(self, op, p, sourceSequence):
     targetSequence = []
     for node in sourceSequence:
         if not isinstance(node,(ModelObject.ModelObject, xml.dom.Node)):
             raise XPathException(p, 'err:XPTY0020', _('Axis step {0} context item is not a node: {1}').format(op, node))
         targetNodes = []
         if isinstance(node, ModelObject.ModelObject): node = node.element
         if isinstance(p,QNameDef):
             ns = p.namespaceURI; localname = p.localName
             if p.isAttribute:
                 if p.unprefixed:
                     if node.hasAttribute(localname):
                         targetNodes.append(node.getAttribute(localname))
                 else:
                     if node.hasAttributeNS(ns,localname):
                         targetNodes.append(node.getAttributeNS(ns,localname))
             elif op == '/' or op is None:
                 targetNodes = XmlUtil.children(node, ns, localname)
             elif op == '//':
                 targetNodes = XmlUtil.descendants(node, ns, localname)
             elif op == '..':
                 targetNodes = [ XmlUtil.parent(node) ]
         elif isinstance(p, OperationDef) and isinstance(p.name,QNameDef):
             if p.name.localName == "text":
                 targetNodes = [XmlUtil.text(node)]
             # todo: add element, attribute, node, etc...
         targetSequence.extend(targetNodes)
     return targetSequence
Example #23
0
    def __init__(self, mainWin, options):
        self.mainWin = mainWin
        parent = mainWin.parent
        super(DialogNewFactItemOptions, self).__init__(parent)
        self.parent = parent
        self.options = options
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))
        self.accepted = False

        self.transient(self.parent)
        self.title(_("New Fact Item Options"))
        
        frame = Frame(self)

        label(frame, 1, 1, "Entity scheme:")
        self.cellEntityIdentScheme = gridCell(frame, 2, 1, getattr(options,"entityIdentScheme",""), width=50)
        ToolTip(self.cellEntityIdentScheme, text=_("Enter the scheme for the context entity identifier"), wraplength=240)
        label(frame, 1, 2, "Entity identifier:")
        self.cellEntityIdentValue = gridCell(frame, 2, 2, getattr(options,"entityIdentValue",""))
        ToolTip(self.cellEntityIdentValue, text=_("Enter the entity identifier value (e.g., stock ticker)"), wraplength=240)
        label(frame, 1, 3, "Start date:")
        startDate = getattr(options,"startDate",None)
        self.cellStartDate = gridCell(frame, 2, 3, XmlUtil.dateunionValue(startDate) if startDate else "")
        ToolTip(self.cellStartDate, text=_("Enter the start date for the report period (e.g., 2010-01-01)"), wraplength=240)
        label(frame, 1, 4, "End date:")
        endDate = getattr(options,"endDate",None)
        self.cellEndDate = gridCell(frame, 2, 4, XmlUtil.dateunionValue(endDate, subtractOneDay=True) if endDate else "")
        ToolTip(self.cellEndDate, text=_("Enter the end date for the report period (e.g., 2010-12-31)"), wraplength=240)
        label(frame, 1, 5, "Monetary unit:")
        self.cellMonetaryUnit = gridCombobox(frame, 2, 5, getattr(options,"monetaryUnit",""), values=monetaryUnits)
        ToolTip(self.cellMonetaryUnit, text=_("Select a monetary unit (e.g., EUR)"), wraplength=240)
        label(frame, 1, 6, "Monetary decimals:")
        self.cellMonetaryDecimals = gridCell(frame, 2, 6, getattr(options,"monetaryDecimals","2"))
        ToolTip(self.cellMonetaryDecimals, text=_("Enter decimals for monetary items"), wraplength=240)
        label(frame, 1, 7, "Non-monetary decimals:")
        self.cellNonMonetaryDecimals = gridCell(frame, 2, 7, getattr(options,"nonMonetaryDecimals","0"))
        ToolTip(self.cellNonMonetaryDecimals, text=_("Enter decimals for non-monetary items (e.g., stock shares)"), wraplength=240)

        cancelButton = Button(frame, text=_("Cancel"), width=8, command=self.close)
        ToolTip(cancelButton, text=_("Cancel operation, discarding changes and entries"))
        okButton = Button(frame, text=_("OK"), width=8, command=self.ok)
        ToolTip(okButton, text=_("Accept the options as entered above"))
        cancelButton.grid(row=8, column=1, columnspan=3, sticky=E, pady=3, padx=3)
        okButton.grid(row=8, column=1, columnspan=3, sticky=E, pady=3, padx=86)
        
        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(2, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        
        #self.bind("<Return>", self.ok)
        #self.bind("<Escape>", self.close)
        
        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
Example #24
0
 def write(self):
     try:
         from arelle import XmlUtil
         with open(self.outfile, "w") as fh:
             XmlUtil.writexml(fh, self.htmlDoc, encoding="utf-8")
         self.modelXbrl.info("info", _("Saved output html to %(file)s"), file=self.outfile)
     except (IOError, EnvironmentError) as err:
         self.modelXbrl.exception("arelle:htmlIOError", _("Failed to save output html to %(file)s: \s%(error)s"), file=self.outfile, error=err)
Example #25
0
 def resultIsInfoset(self):
     if self.modelDocument.outpath:
         result = XmlUtil.descendant(self, None, "result")
         if result is not None:
             return XmlUtil.child(result, None,
                                  "file") is not None or XmlUtil.text(
                                      result).endswith(".xml")
     return False
Example #26
0
 def resultInfosetUri(self):
     result = XmlUtil.descendant(self, None, "result")
     if result is not None:
         child = XmlUtil.child(result, None, "file")
         return os.path.join(
             self.modelDocument.outpath,
             XmlUtil.text(child if child is not None else result))
     return None
Example #27
0
 def dataUris(self):
     try:
         return self._dataUris
     except AttributeError:
         self._dataUris = defaultdict(list) # may contain instances, schemas, linkbases
         for dataElement in XmlUtil.descendants(self, None, ("data", "input")):
             for elt in XmlUtil.descendants(dataElement, None, ("xsd", "schema", "linkbase", "instance")):
                 self._dataUris["schema" if elt.localName == "xsd" else elt.localName].append(elt.textValue.strip())
         return self._dataUris
 def aspectsCovered(self):
     aspectsCovered = set()
     if XmlUtil.hasChild(self, XbrlConst.euRend, "primaryItem"):
         aspectsCovered.add(Aspect.CONCEPT)
     if XmlUtil.hasChild(self, XbrlConst.euRend, "timeReference"):
         aspectsCovered.add(Aspect.INSTANT)
     for e in XmlUtil.children(self, XbrlConst.euRend, "explicitDimCoord"):
         aspectsCovered.add(self.prefixedNameQname(e.get("dimension")))
     return aspectsCovered
Example #29
0
 def __repr__(self):
     return ("modelContext[{0}, period: {1}, {2}{3} line {4}]"
             .format(self.id,
                     "forever" if self.isForeverPeriod else
                     "instant " + XmlUtil.dateunionValue(self.instantDatetime, subtractOneDay=True) if self.isInstantPeriod else
                     "duration " + XmlUtil.dateunionValue(self.startDatetime) + " - " + XmlUtil.dateunionValue(self.endDatetime, subtractOneDay=True),
                     "dimensions: ({0}) {1},".format(len(self.qnameDims),
                     tuple(mem.propertyView for dim,mem in sorted(self.qnameDims.items())))
                     if self.qnameDims else "",
                     self.modelDocument.basename, self.sourceline))
Example #30
0
 def propertyView(self):
     scheme, entityId = self.entityIdentifier
     return ((("entity", entityId, (("scheme", scheme),)),) +
             ((("forever", ""),) if self.isForeverPeriod else
             (("instant", XmlUtil.dateunionValue(self.instantDatetime, subtractOneDay=True)),) if self.isInstantPeriod else
             (("startDate", XmlUtil.dateunionValue(self.startDatetime)),("endDate", XmlUtil.dateunionValue(self.endDatetime, subtractOneDay=True)))) +
             (("dimensions", "({0})".format(len(self.qnameDims)),
               tuple(mem.propertyView for dim,mem in sorted(self.qnameDims.items())))
               if self.qnameDims else (),
             ))
Example #31
0
 def evaluate(self,
              exprStack,
              contextItem=None,
              resultStack=None,
              parentOp=None):
     if resultStack is None: resultStack = []
     if contextItem is None: contextItem = self.contextItem
     setProgHeader = False
     for p in exprStack:
         result = None
         if isinstance(p, QNameDef) or (p == '*' and parentOp in ('/', '//')
                                        ):  # path step QName or wildcard
             # step axis operation
             if len(resultStack) == 0 or not self.isNodeSequence(
                     resultStack[-1]):
                 resultStack.append([
                     contextItem,
                 ])
             result = self.stepAxis(parentOp, p, resultStack.pop())
         elif isinstance(p, _STR_NUM_TYPES):
             result = p
         elif isinstance(p, VariableRef):
             if p.name in self.inScopeVars:
                 result = self.inScopeVars[p.name]
                 # uncomment to allow lambdas as variable values (for deferred processing if needed)
                 #if isinstance(result, LambdaType):
                 #    result = result()  # dereference lambda-valued variables
                 if result is None:  # None atomic result is XPath empty sequence
                     result = [
                     ]  # subsequent processing discards None results
         elif isinstance(p, OperationDef):
             op = p.name
             if isinstance(op, QNameDef):  # function call
                 args = self.evaluate(p.args, contextItem=contextItem)
                 ns = op.namespaceURI
                 localname = op.localName
                 try:
                     from arelle import (FunctionXs, FunctionFn,
                                         FunctionXfi, FunctionIxt,
                                         FunctionCustom)
                     if op in self.modelXbrl.modelCustomFunctionSignatures:
                         result = FunctionCustom.call(
                             self, p, op, contextItem, args)
                     elif op.unprefixed and localname in {
                             'attribute', 'comment', 'document-node',
                             'element', 'item', 'node',
                             'processing-instruction', 'schema-attribute',
                             'schema-element', 'text'
                     }:
                         # step axis operation
                         if len(resultStack
                                ) == 0 or not self.isNodeSequence(
                                    resultStack[-1]):
                             if isinstance(contextItem, (tuple, list)):
                                 resultStack.append(contextItem)
                             else:
                                 resultStack.append([
                                     contextItem,
                                 ])
                         result = self.stepAxis(parentOp, p,
                                                resultStack.pop())
                     elif op.unprefixed or ns == XbrlConst.fn:
                         result = FunctionFn.call(self, p, localname,
                                                  contextItem, args)
                     elif ns == XbrlConst.xfi or ns == XbrlConst.xff:
                         result = FunctionXfi.call(self, p, localname, args)
                     elif ns == XbrlConst.xsd:
                         result = FunctionXs.call(self, p, localname, args)
                     elif ns in FunctionIxt.ixtNamespaceFunctions:
                         result = FunctionIxt.call(self, p, op, args)
                     elif op in self.modelXbrl.modelManager.customTransforms:
                         result = self.modelXbrl.modelManager.customTransforms[
                             op](args[0][0])
                     else:
                         raise XPathException(
                             p, 'err:XPST0017',
                             _('Function call not identified: {0}.').format(
                                 op))
                 except FunctionNumArgs as err:
                     raise XPathException(p, err.errCode,
                                          "{}: {}".format(err.errText, op))
                 except FunctionArgType as err:
                     raise XPathException(
                         p, err.errCode,
                         _('Argument {0} does not match expected type {1} for {2} {3}.'
                           ).format(err.argNum, err.expectedType, op,
                                    err.foundObject))
                 except FunctionNotAvailable:
                     raise XPathException(
                         p, 'err:XPST0017',
                         _('Function named {0} does not have a custom or built-in implementation.'
                           ).format(op))
             elif op in VALUE_OPS:
                 # binary arithmetic operations and value comparisons
                 s1 = self.atomize(
                     p, resultStack.pop()) if len(resultStack) > 0 else []
                 s2 = self.atomize(
                     p, self.evaluate(p.args, contextItem=contextItem))
                 # value comparisons
                 if len(s1) > 1 or len(s2) > 1:
                     raise XPathException(
                         p, 'err:XPTY0004',
                         _("Value operation '{0}' sequence length error").
                         format(op))
                 if len(s1) == 0 or len(s2) == 0:
                     result = []
                 else:
                     op1 = s1[0]
                     op2 = s2[0]
                     from arelle.FunctionUtil import (testTypeCompatiblity)
                     testTypeCompatiblity(self, p, op, op1, op2)
                     if type(op1) != type(op2) and op in ('+', '-', '*',
                                                          'div', 'idiv',
                                                          'mod'):
                         # check if type promotion needed (Decimal-float, not needed for integer-Decimal)
                         if isinstance(op1, Decimal) and isinstance(
                                 op2, float):
                             op1 = float(
                                 op1
                             )  # per http://http://www.w3.org/TR/xpath20/#dt-type-promotion 1b
                         elif isinstance(op2, Decimal) and isinstance(
                                 op1, float):
                             op2 = float(op2)
                     if op == '+':
                         result = op1 + op2
                     elif op == '-':
                         result = op1 - op2
                     elif op == '*':
                         result = op1 * op2
                     elif op in ('div', 'idiv', "mod"):
                         try:
                             if op == 'div':
                                 result = op1 / op2
                             elif op == 'idiv':
                                 result = op1 // op2
                             elif op == 'mod':
                                 result = op1 % op2
                         except ZeroDivisionError:
                             raise XPathException(
                                 p, 'err:FOAR0001',
                                 _('Attempt to divide by zero: {0} {1} {2}.'
                                   ).format(op1, op, op2))
                     elif op == 'ge':
                         result = op1 >= op2
                     elif op == 'gt':
                         result = op1 > op2
                     elif op == 'le':
                         result = op1 <= op2
                     elif op == 'lt':
                         result = op1 < op2
                     elif op == 'eq':
                         result = op1 == op2
                     elif op == 'ne':
                         result = op1 != op2
                     elif op == 'to':
                         result = _RANGE(_INT(op1), _INT(op2) + 1)
             elif op in GENERALCOMPARISON_OPS:
                 # general comparisons
                 s1 = self.atomize(
                     p, resultStack.pop()) if len(resultStack) > 0 else []
                 s2 = self.atomize(
                     p, self.evaluate(p.args, contextItem=contextItem))
                 result = []
                 for op1 in s1:
                     for op2 in s2:
                         if op == '>=':
                             result = op1 >= op2
                         elif op == '>':
                             result = op1 > op2
                         elif op == '<=':
                             result = op1 <= op2
                         elif op == '<':
                             result = op1 < op2
                         elif op == '=':
                             result = op1 == op2
                         elif op == '!=':
                             result = op1 != op2
                         if result:
                             break
                     if result:
                         break
             elif op in NODECOMPARISON_OPS:
                 # node comparisons
                 s1 = resultStack.pop() if len(resultStack) > 0 else []
                 s2 = self.evaluate(p.args, contextItem=contextItem)
                 if len(s1) > 1 or len(s2) > 1 or not self.isNodeSequence(
                         s1) or not self.isNodeSequence(s2[0]):
                     raise XPathException(
                         p, 'err:XPTY0004',
                         _('Node comparison sequence error'))
                 if len(s1) == 0 or len(s2[0]) == 0:
                     result = []
                 else:
                     n1 = s1[0]
                     n2 = s2[0][0]
                     result = False
                     for op1 in s1:
                         for op2 in s2:
                             if op == 'is':
                                 result = n1 == n2
                             elif op == '>>':
                                 result = op1 > op2
                             elif op == '<<':
                                 result = op1 <= op2
                         if result:
                             break
             elif op in COMBINING_OPS:
                 # node comparisons
                 s1 = resultStack.pop() if len(resultStack) > 0 else []
                 s2 = self.flattenSequence(
                     self.evaluate(p.args, contextItem=contextItem))
                 if not self.isNodeSequence(s1) or not self.isNodeSequence(
                         s2):
                     raise XPathException(
                         p, 'err:XPTY0004',
                         _('Node operation sequence error'))
                 set1 = set(s1)
                 set2 = set(s2)
                 if op == 'intersect':
                     resultset = set1 & set2
                 elif op == 'except':
                     resultset = set1 - set2
                 elif op == 'union' or op == '|':
                     resultset = set1 | set2
                 # convert to a list in document order
                 result = self.documentOrderedNodes(resultset)
             elif op in LOGICAL_OPS:
                 # general comparisons
                 if len(resultStack) == 0:
                     result = []
                 else:
                     op1 = self.effectiveBooleanValue(p, resultStack.pop(
                     )) if len(resultStack) > 0 else False
                     op2 = self.effectiveBooleanValue(
                         p, self.evaluate(p.args, contextItem=contextItem))
                     result = False
                     if op == 'and':
                         result = op1 and op2
                     elif op == 'or':
                         result = op1 or op2
             elif op in UNARY_OPS:
                 s1 = self.atomize(
                     p, self.evaluate(p.args, contextItem=contextItem))
                 if len(s1) > 1:
                     raise XPathException(
                         p, 'err:XPTY0004',
                         _('Unary expression sequence length error'))
                 if len(s1) == 0:
                     result = []
                 else:
                     op1 = s1[0]
                     if op == 'u+':
                         result = op1
                     elif op == 'u-':
                         result = -op1
             elif op == 'instance':
                 result = False
                 s1 = self.flattenSequence(
                     resultStack.pop()) if len(resultStack) > 0 else []
                 arity = len(s1)
                 if len(p.args) > 1:
                     occurenceIndicator = p.args[1]
                     if (occurenceIndicator == '?' and arity in (0,1) ) or \
                        (occurenceIndicator == '+' and arity >= 1) or \
                        (occurenceIndicator == '*'):
                         result = True
                 elif arity == 1:
                     result = True
                 if result and len(p.args) > 0:
                     t = p.args[0]
                     for x in s1:
                         if isinstance(t, QNameDef):
                             if t.namespaceURI == XbrlConst.xsd:
                                 tType = {
                                     "integer": _INT_TYPES,
                                     "string": _STR_BASE,
                                     "decimal": Decimal,
                                     "double": float,
                                     "float": float,
                                     "boolean": bool,
                                     "QName": QName,
                                     "anyURI": AnyURI,
                                     "date": DateTime,
                                     "dateTime": DateTime,
                                 }.get(t.localName)
                                 if tType:
                                     result = isinstance(x, tType)
                                     if result and tType == DateTime:
                                         result = x.dateOnly == (
                                             t.localName == "date")
                         elif isinstance(t, OperationDef):
                             if t.name == "element":
                                 if isinstance(x, ModelObject):
                                     if len(t.args) >= 1:
                                         qn = t.args[0]
                                         if qn == '*' or (isinstance(
                                                 qn, QNameDef) and qn == x):
                                             result = True
                                             if len(t.args
                                                    ) >= 2 and isinstance(
                                                        t.args[1],
                                                        QNameDef):
                                                 modelXbrl = x.modelDocument.modelXbrl
                                                 modelConcept = modelXbrl.qnameConcepts.get(
                                                     qname(x))
                                                 if not modelConcept.instanceOfType(
                                                         t.args[1]):
                                                     result = False
                                 else:
                                     result = False
                             # elif t.name == "item" comes here and result stays True
                         if not result:
                             break
             elif op == 'sequence':
                 result = self.evaluate(p.args, contextItem=contextItem)
             elif op == 'predicate':
                 result = self.predicate(
                     p, resultStack.pop()) if len(resultStack) > 0 else []
             elif op in FORSOMEEVERY_OPS:  # for, some, every
                 result = []
                 self.evaluateRangeVars(op, p.args[0], p.args[1:],
                                        contextItem, result)
             elif op == 'if':
                 test = self.effectiveBooleanValue(
                     p,
                     self.evaluate(p.args[0].expr[0],
                                   contextItem=contextItem))
                 result = self.evaluate(p.args[1 if test else 2].args,
                                        contextItem=contextItem)
             elif op == '.':
                 result = contextItem
             elif op == '..':
                 result = XmlUtil.parent(contextItem)
             elif op in PATH_OPS:
                 if op in ('rootChild', 'rootDescendant'):
                     # fix up for multi-instance
                     resultStack.append([
                         self.inputXbrlInstance.xmlDocument,
                     ])
                     op = '/' if op == 'rootChild' else '//'
                 # contains QNameDefs and predicates
                 if len(resultStack) > 0:
                     innerFocusNodes = resultStack.pop()
                 else:
                     innerFocusNodes = contextItem
                 navSequence = []
                 for innerFocusNode in self.flattenSequence(
                         innerFocusNodes):
                     navSequence += self.evaluate(
                         p.args, contextItem=innerFocusNode, parentOp=op)
                 result = self.documentOrderedNodes(
                     self.flattenSequence(navSequence))
         elif isinstance(p, ProgHeader):
             self.progHeader = p
             from arelle.ModelFormulaObject import Trace
             if p.traceType not in (Trace.MESSAGE, Trace.CUSTOM_FUNCTION):
                 self.traceType = p.traceType
             setProgHeader = True
         if result is not None:  # note: result can be False which gets appended to resultStack
             resultStack.append(self.flattenSequence(result))
     if setProgHeader:
         self.progHeader = None
     return resultStack
Example #32
0
def generateUpdatedTableLB(dts, updatedTableLinkbaseFile):
    import os, io
    from arelle import XmlUtil, XbrlConst
    from arelle.ViewUtil import viewReferences, referenceURI
    from arelle.ModelRenderingObject import ModelEuAxisCoord

    if dts.fileSource.isArchive:
        dts.error(
            "genTblLB:outFileIsArchive",
            _("Updated Table Linkbase file cannot be an archive: %(tableLBOutputFile)s."
              ),
            modelObject=dts,
            tableLBOutputFile=updatedTableLinkbaseFile)
        return
    tblAxisRelSet = dts.relationshipSet(XbrlConst.euTableAxis)
    axisMbrRelSet = dts.relationshipSet(XbrlConst.euAxisMember)
    if len(tblAxisRelSet.modelRelationships) == 0:
        dts.error(
            "genTblLB:noInputTables",
            _("DTS does not contain Eurofiling 2010 tables and axes: %(entryFile)s."
              ),
            modelObject=dts,
            entryFile=dts.uri)
        return

    file = io.StringIO('''
<nsmap>
<link:linkbase 
xmlns:label="http://xbrl.org/2008/label"
xmlns:gen="http://xbrl.org/2008/generic"
xmlns:df="http://xbrl.org/2008/filter/dimension"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:reference="http://xbrl.org/2008/reference"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:link="http://www.xbrl.org/2003/linkbase"
xmlns:table="http://xbrl.org/2011/table"
xmlns:formula="http://xbrl.org/2008/formula"
xsi:schemaLocation="             
http://www.xbrl.org/2003/linkbase http://www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd
http://xbrl.org/2008/generic http://www.xbrl.org/2008/generic-link.xsd
http://xbrl.org/2008/reference http://www.xbrl.org/2008/generic-reference.xsd
http://xbrl.org/2008/label http://www.xbrl.org/2008/generic-label.xsd
http://xbrl.org/2011/table http://www.xbrl.org/2011/table.xsd
http://xbrl.org/2008/filter/dimension http://www.xbrl.org/2008/dimension-filter.xsd">
  <link:arcroleRef arcroleURI="http://xbrl.org/arcrole/2011/table-filter" xlink:type="simple" 
   xlink:href="http://www.xbrl.org/2011/table.xsd#table-filter"/>
  <link:arcroleRef arcroleURI="http://xbrl.org/arcrole/2011/table-axis" xlink:type="simple"
   xlink:href="http://www.xbrl.org/2011/table.xsd#table-axis"/>
  <link:arcroleRef arcroleURI="http://xbrl.org/arcrole/2011/axis-subtree" xlink:type="simple"
   xlink:href="http://www.xbrl.org/2011/table.xsd#axis-subtree"/>
  <link:arcroleRef arcroleURI="http://xbrl.org/arcrole/2011/axis-filter" xlink:type="simple"
   xlink:href="http://www.xbrl.org/2011/filter-axis.xsd#axis-filter"/>
</link:linkbase>
</nsmap>
<!--  Generated by Arelle(r) http://arelle.org --> 
''')
    from arelle.ModelObjectFactory import parser
    parser, parserLookupName, parserLookupClass = parser(dts, None)
    from lxml import etree
    xmlDocument = etree.parse(file,
                              parser=parser,
                              base_url=updatedTableLinkbaseFile)
    file.close()
    nsmapElt = xmlDocument.getroot()
    #xmlDocument.getroot().init(self)  ## is this needed ??
    for lbElement in xmlDocument.iter(
            tag="{http://www.xbrl.org/2003/linkbase}linkbase"):
        break

    class DocObj:  # fake ModelDocument for namespaces
        def __init__(self):
            self.xmlRootElement = lbElement
            self.xmlDocument = xmlDocument

    docObj = DocObj()

    numELRs = 0
    numTables = 0

    def copyAttrs(fromElt, toElt, attrTags):
        for attr in attrTags:
            if fromElt.get(attr):
                toElt.set(attr, fromElt.get(attr))

    def generateTable(newLinkElt, newTblElt, srcTblElt, tblAxisRelSet,
                      axisMbrRelSet, visited):
        if srcTblElt is not None:
            for rel in tblAxisRelSet.fromModelObject(srcTblElt):
                srcAxisElt = rel.toModelObject
                if isinstance(srcAxisElt, ModelEuAxisCoord):
                    visited.add(srcAxisElt)
                    newAxisElt = etree.SubElement(
                        newLinkElt, "{http://xbrl.org/2011/table}ruleAxis")
                    copyAttrs(srcAxisElt, newAxisElt,
                              ("id", "{http://www.w3.org/1999/xlink}type",
                               "{http://www.w3.org/1999/xlink}label"))
                    newAxisElt.set("abstract",
                                   "true")  # always true on root element
                    newArcElt = etree.SubElement(
                        newLinkElt, "{http://xbrl.org/2011/table}axisArc")
                    copyAttrs(rel, newArcElt,
                              ("id", "{http://www.w3.org/1999/xlink}type",
                               "{http://www.w3.org/1999/xlink}from",
                               "{http://www.w3.org/1999/xlink}to", "order"))
                    newArcElt.set("{http://www.w3.org/1999/xlink}arcrole",
                                  XbrlConst.tableBreakdown)
                    newArcElt.set("axisDisposition", rel.axisDisposition)
                    generateAxis(newLinkElt, newAxisElt, srcAxisElt,
                                 axisMbrRelSet, visited)
                    visited.discard(srcAxisElt)

    def generateAxis(newLinkElt, newAxisParentElt, srcAxisElt, axisMbrRelSet,
                     visited):
        for rel in axisMbrRelSet.fromModelObject(srcAxisElt):
            tgtAxisElt = rel.toModelObject
            if isinstance(tgtAxisElt,
                          ModelEuAxisCoord) and tgtAxisElt not in visited:
                visited.add(tgtAxisElt)
                newAxisElt = etree.SubElement(
                    newLinkElt, "{http://xbrl.org/2011/table}ruleAxis")
                copyAttrs(
                    tgtAxisElt, newAxisElt,
                    ("id", "abstract", "{http://www.w3.org/1999/xlink}type",
                     "{http://www.w3.org/1999/xlink}label"))
                if tgtAxisElt.primaryItemQname:
                    newRuleElt = etree.SubElement(
                        newAxisElt, "{http://xbrl.org/2008/formula}concept")
                    newQnameElt = etree.SubElement(
                        newRuleElt, "{http://xbrl.org/2008/formula}qname")
                    newQnameElt.text = XmlUtil.addQnameValue(
                        docObj, tgtAxisElt.primaryItemQname)
                for dimQname, memQname in tgtAxisElt.explicitDims:
                    newRuleElt = etree.SubElement(
                        newAxisElt,
                        "{http://xbrl.org/2008/formula}explicitDimension")
                    newRuleElt.set("dimension",
                                   XmlUtil.addQnameValue(docObj, dimQname))
                    newMbrElt = etree.SubElement(
                        newRuleElt, "{http://xbrl.org/2008/formula}member")
                    newQnameElt = etree.SubElement(
                        newMbrElt, "{http://xbrl.org/2008/formula}qname")
                    newQnameElt.text = XmlUtil.addQnameValue(docObj, memQname)
                newArcElt = etree.SubElement(
                    newLinkElt, "{http://xbrl.org/2011/table}axisArc")
                copyAttrs(rel, newArcElt,
                          ("id", "{http://www.w3.org/1999/xlink}type",
                           "{http://www.w3.org/1999/xlink}from",
                           "{http://www.w3.org/1999/xlink}to", "order"))
                newArcElt.set("{http://www.w3.org/1999/xlink}arcrole",
                              XbrlConst.tableAxisSubtree)
                generateAxis(newLinkElt, newAxisElt, tgtAxisElt, axisMbrRelSet,
                             visited)
                visited.discard(tgtAxisElt)

    # sort URIs
    linkroleUris = sorted(
        [linkroleUri for linkroleUri in tblAxisRelSet.linkRoleUris])

    firstNewLinkElt = None
    roleRefUris = set()
    for linkroleUri in linkroleUris:
        numELRs += 1
        newLinkElt = etree.SubElement(lbElement,
                                      "{http://xbrl.org/2008/generic}link")
        newLinkElt.set("{http://www.w3.org/1999/xlink}type", "extended")
        newLinkElt.set("{http://www.w3.org/1999/xlink}role", linkroleUri)
        if firstNewLinkElt is None: firstNewLinkElt = newLinkElt
        # To do: add roleRef if needed
        tblAxisRelSet = dts.relationshipSet(XbrlConst.euTableAxis, linkroleUri)
        axisMbrRelSet = dts.relationshipSet(XbrlConst.euAxisMember,
                                            linkroleUri)
        for srcTblElt in tblAxisRelSet.rootConcepts:
            if srcTblElt.tag == "{http://www.eurofiling.info/2010/rendering}table":
                numTables += 1
                newTblElt = etree.SubElement(
                    newLinkElt, "{http://xbrl.org/2011/table}table")
                newTblElt.set("aspectModel", "dimensional")
                copyAttrs(srcTblElt, newTblElt,
                          ("id", "{http://www.w3.org/1999/xlink}type",
                           "{http://www.w3.org/1999/xlink}label"))
                generateTable(newLinkElt, newTblElt, srcTblElt, tblAxisRelSet,
                              axisMbrRelSet, set())

                if linkroleUri not in roleRefUris:
                    srcRoleRefElt = XmlUtil.descendant(srcTblElt.getroottree(),
                                                       XbrlConst.link,
                                                       "roleRef", "roleURI",
                                                       linkroleUri)
                    if srcRoleRefElt is not None:
                        roleRefUris.add(linkroleUri)
                        newRoleRefElt = etree.Element(
                            "{http://www.xbrl.org/2003/linkbase}roleRef")
                        copyAttrs(
                            srcRoleRefElt, newRoleRefElt,
                            ("roleURI", "{http://www.w3.org/1999/xlink}type",
                             "{http://www.w3.org/1999/xlink}href"))
                        firstNewLinkElt.addprevious(newRoleRefElt)

    fh = open(updatedTableLinkbaseFile, "w", encoding="utf-8")
    XmlUtil.writexml(fh, xmlDocument, encoding="utf-8")
    fh.close()

    dts.info(
        "info:updateTableLinkbase",
        _("Updated Table Linkbase of %(entryFile)s has %(numberOfLinkroles)s linkroles, %(numberOfTables)s tables in file %(tableLBOutputFile)s."
          ),
        modelObject=dts,
        entryFile=dts.uri,
        numberOfLinkroles=numELRs,
        numberOfTables=numTables,
        tableLBOutputFile=updatedTableLinkbaseFile)
Example #33
0
def load(modelXbrl,
         uri,
         base=None,
         isEntry=False,
         isIncluded=None,
         namespace=None,
         reloadCache=False):
    normalizedUri = modelXbrl.modelManager.cntlr.webCache.normalizeUrl(
        uri, base)
    if isEntry:
        modelXbrl.uri = normalizedUri
        modelXbrl.uriDir = os.path.dirname(normalizedUri)
        for i in range(modelXbrl.modelManager.disclosureSystem.
                       maxSubmissionSubdirectoryEntryNesting):
            modelXbrl.uriDir = os.path.dirname(modelXbrl.uriDir)
    if modelXbrl.modelManager.validateDisclosureSystem and \
       not normalizedUri.startswith(modelXbrl.uriDir) and \
       not modelXbrl.modelManager.disclosureSystem.hrefValid(normalizedUri):
        blocked = modelXbrl.modelManager.disclosureSystem.blockDisallowedReferences
        modelXbrl.error(
            "Prohibited file for filings{1}: {0}".format(
                normalizedUri,
                _(" blocked") if blocked else ""), "err", "EFM.6.22.02",
            "GFM.1.1.3", "SBR.NL.2.1.0.06")
        if blocked:
            return None
    if normalizedUri in modelXbrl.modelManager.disclosureSystem.mappedFiles:
        mappedUri = modelXbrl.modelManager.disclosureSystem.mappedFiles[
            normalizedUri]
    else:  # handle mapped paths
        mappedUri = normalizedUri
        for mapFrom, mapTo in modelXbrl.modelManager.disclosureSystem.mappedPaths:
            if normalizedUri.startswith(mapFrom):
                mappedUri = mapTo + normalizedUri[len(mapFrom):]
                break
    if modelXbrl.fileSource.isInArchive(mappedUri):
        filepath = mappedUri
    else:
        filepath = modelXbrl.modelManager.cntlr.webCache.getfilename(
            mappedUri, reload=reloadCache)
        if filepath:
            uri = modelXbrl.modelManager.cntlr.webCache.normalizeUrl(filepath)
    if filepath is None:  # error such as HTTPerror is already logged
        modelXbrl.error("File can not be loaded: {0}".format(mappedUri), "err",
                        "FileNotLoadable")
        type = Type.Unknown
        return None

    modelDocument = modelXbrl.urlDocs.get(mappedUri)
    if modelDocument:
        return modelDocument

    # load XML and determine type of model document
    modelXbrl.modelManager.showStatus(_("parsing {0}").format(uri))
    file = None
    try:
        if modelXbrl.modelManager.validateDisclosureSystem:
            file = ValidateFilingText.checkfile(modelXbrl, filepath)
        else:
            file = modelXbrl.fileSource.file(filepath)
        xmlDocument = xml.dom.minidom.parse(file)
        file.close()
    except EnvironmentError as err:
        modelXbrl.error(
            "{0}: file error: {1}".format(os.path.basename(uri), err), "err",
            "IOerror")
        type = Type.Unknown
        if file:
            file.close()
        return None
    except (
            xml.parsers.expat.ExpatError, xml.dom.DOMException, ValueError
    ) as err:  # ValueError raised on bad format of qnames, xmlns'es, or parameters
        modelXbrl.error(
            "{0}: import error: {1}".format(os.path.basename(uri), err), "err",
            "XMLsyntax")
        type = Type.Unknown
        if file:
            file.close()
        return None

    # identify document
    #modelXbrl.modelManager.addToLog("discovery: {0}".format(
    #            os.path.basename(uri)))
    modelXbrl.modelManager.showStatus(_("loading {0}").format(uri))
    modelDocument = None

    for rootNode in xmlDocument.childNodes:
        if rootNode.nodeType == 1:  #element
            ln = rootNode.localName
            ns = rootNode.namespaceURI

            # type classification
            if ns == XbrlConst.xsd and ln == "schema":
                type = Type.SCHEMA
            elif ns == XbrlConst.link:
                if ln == "linkbase":
                    type = Type.LINKBASE
                elif ln == "xbrl":
                    type = Type.INSTANCE
            elif ns == XbrlConst.xbrli:
                if ln == "xbrl":
                    type = Type.INSTANCE
            elif ns == XbrlConst.xhtml and \
                 ln == "html" or ln == "xhtml":
                type = Type.Unknown
                for i in range(len(rootNode.attributes)):
                    if rootNode.attributes.item(i).value == XbrlConst.ixbrl:
                        type = Type.INLINEXBRL
                        break
                XmlUtil.markIdAttributes(
                    rootNode)  # required for minidom searchability
            elif ln == "report" and ns == XbrlConst.ver:
                type = Type.VERSIONINGREPORT
            elif ln == "testcases" or ln == "documentation":
                type = Type.TESTCASESINDEX
            elif ln == "testcase":
                type = Type.TESTCASE
            elif ln == "registry" and ns == XbrlConst.registry:
                type = Type.REGISTRY
            elif ln == "rss":
                type = Type.RSSFEED
            else:
                type = Type.Unknown
                nestedInline = XmlUtil.descendant(rootNode, XbrlConst.xhtml,
                                                  ("html", "xhtml"))
                if nestedInline:
                    for i in range(len(nestedInline.attributes)):
                        if nestedInline.attributes.item(
                                i).value == XbrlConst.ixbrl:
                            type = Type.INLINEXBRL
                            rootNode = nestedInline
                            break
                XmlUtil.markIdAttributes(
                    rootNode)  # required for minidom searchability

            #create modelDocument object or subtype as identified
            if type == Type.VERSIONINGREPORT:
                from arelle.ModelVersReport import ModelVersReport
                modelDocument = ModelVersReport(modelXbrl, type, mappedUri,
                                                filepath, xmlDocument)
            elif type == Type.RSSFEED:
                from arelle.ModelRssObject import ModelRssObject
                modelDocument = ModelRssObject(modelXbrl, type, mappedUri,
                                               filepath, xmlDocument)
            else:
                modelDocument = ModelDocument(modelXbrl, type, mappedUri,
                                              filepath, xmlDocument)
            modelDocument.xmlRootElement = rootNode
            modelDocument.schemaLocationElements.add(rootNode)

            if isEntry:
                modelDocument.inDTS = True

            # discovery (parsing)
            if type == Type.SCHEMA:
                modelDocument.schemaDiscover(rootNode, isIncluded, namespace)
            elif type == Type.LINKBASE:
                modelDocument.linkbaseDiscover(rootNode)
            elif type == Type.INSTANCE:
                modelDocument.instanceDiscover(rootNode)
            elif type == Type.INLINEXBRL:
                modelDocument.inlineXbrlDiscover(rootNode)
            elif type == Type.VERSIONINGREPORT:
                modelDocument.versioningReportDiscover(rootNode)
            elif type == Type.TESTCASESINDEX:
                modelDocument.testcasesIndexDiscover(xmlDocument)
            elif type == Type.TESTCASE:
                modelDocument.testcaseDiscover(rootNode)
            elif type == Type.REGISTRY:
                modelDocument.registryDiscover(rootNode)
            elif type == Type.VERSIONINGREPORT:
                modelDocument.versioningReportDiscover(rootNode)
            elif type == Type.RSSFEED:
                modelDocument.rssFeedDiscover(rootNode)
            break
    return modelDocument
Example #34
0
 def customAttributeQname(self, eventName):
     custAttrElt = XmlUtil.child(self, XbrlConst.verce, eventName)
     if custAttrElt is not None and custAttrElt.get("name"):
         return qname(custAttrElt, custAttrElt.get("name"))
     return None
Example #35
0
 def fromConceptQname(self):
     fromConcept = XmlUtil.child(self, XbrlConst.vercb, "fromConcept")
     if fromConcept is not None and fromConcept.get("name"):
         return qname(fromConcept, fromConcept.get("name"))
     else:
         return None
Example #36
0
File: DTS.py Project: ymawji/Arelle
def checkFilingDTS(val, modelDocument, isEFM, isGFM, visited):
    global targetNamespaceDatePattern, efmFilenamePattern, htmlFileNamePattern, roleTypePattern, arcroleTypePattern, \
            arcroleDefinitionPattern, namePattern, linkroleDefinitionBalanceIncomeSheet
    if targetNamespaceDatePattern is None:
        targetNamespaceDatePattern = re.compile(
            r"/([12][0-9]{3})-([01][0-9])-([0-3][0-9])|"
            r"/([12][0-9]{3})([01][0-9])([0-3][0-9])|")
        efmFilenamePattern = re.compile(
            r"^[a-z0-9][a-zA-Z0-9_\.\-]*(\.xsd|\.xml|\.htm)$")
        htmlFileNamePattern = re.compile(
            r"^[a-zA-Z0-9][._a-zA-Z0-9-]*(\.htm)$")
        roleTypePattern = re.compile(r"^.*/role/[^/\s]+$")
        arcroleTypePattern = re.compile(r"^.*/arcrole/[^/\s]+$")
        arcroleDefinitionPattern = re.compile(
            r"^.*[^\\s]+.*$")  # at least one non-whitespace character
        namePattern = re.compile(
            "[][()*+?\\\\/^{}|@#%^=~`\"';:,<>&$\u00a3\u20ac]"
        )  # u20ac=Euro, u00a3=pound sterling
        linkroleDefinitionBalanceIncomeSheet = re.compile(
            r"[^-]+-\s+Statement\s+-\s+.*(income|balance|financial\W+position)",
            re.IGNORECASE)
    nonDomainItemNameProblemPattern = re.compile(
        r"({0})|(FirstQuarter|SecondQuarter|ThirdQuarter|FourthQuarter|[1-4]Qtr|Qtr[1-4]|ytd|YTD|HalfYear)(?:$|[A-Z\W])"
        .format(re.sub(r"\W", "", (val.entityRegistrantName or "").title())))

    visited.append(modelDocument)
    for referencedDocument, modelDocumentReference in modelDocument.referencesDocument.items(
    ):
        #6.07.01 no includes
        if modelDocumentReference.referenceType == "include":
            val.modelXbrl.error(
                ("EFM.6.07.01", "GFM.1.03.01"),
                _("Taxonomy schema %(schema)s includes %(include)s, only import is allowed"
                  ),
                modelObject=modelDocumentReference.referringModelObject,
                schema=modelDocument.basename,
                include=referencedDocument.basename)
        if referencedDocument not in visited and referencedDocument.inDTS:  # ignore EdgarRenderer added non-DTS documents
            checkFilingDTS(val, referencedDocument, isEFM, isGFM, visited)

    if val.disclosureSystem.standardTaxonomiesDict is None:
        pass

    if isEFM:
        if modelDocument.uri in val.disclosureSystem.standardTaxonomiesDict:
            if modelDocument.targetNamespace:
                # check for duplicates of us-types, dei, and rr taxonomies
                for pattern, indexGroup in ((usNamespacesConflictPattern, 2),
                                            (ifrsNamespacesConflictPattern,
                                             2)):
                    match = pattern.match(modelDocument.targetNamespace)
                    if match is not None:
                        conflictClass = match.group(indexGroup)
                        if (conflictClass == 'us-gaap' and match.group(3) <
                                '2018') or conflictClass == 'srt':
                            val.standardNamespaceConflicts['srt+us-gaap'].add(
                                modelDocument
                            )  # ignore non-srt multi-usgaap in Filing.py
                        if conflictClass == 'us-gaap' or conflictClass == 'ifrs-full':
                            val.standardNamespaceConflicts['ifrs+us-gaap'].add(
                                modelDocument)
                        if conflictClass not in ('us-gaap', 'srt'):
                            val.standardNamespaceConflicts[conflictClass].add(
                                modelDocument)

        else:
            if len(modelDocument.basename) > 32:
                val.modelXbrl.error(
                    "EFM.5.01.01.tooManyCharacters",
                    _("Document file name %(filename)s must not exceed 32 characters."
                      ),
                    modelObject=modelDocument,
                    filename=modelDocument.basename)
            if modelDocument.type == ModelDocument.Type.INLINEXBRL:
                if not htmlFileNamePattern.match(modelDocument.basename):
                    val.modelXbrl.error(
                        "EFM.5.01.01",
                        _("Document file name %(filename)s must start with a-z or 0-9, contain upper or lower case letters, ., -, _, and end with .htm."
                          ),
                        modelObject=modelDocument,
                        filename=modelDocument.basename)
            elif not efmFilenamePattern.match(modelDocument.basename):
                val.modelXbrl.error(
                    "EFM.5.01.01",
                    _("Document file name %(filename)s must start with a-z or 0-9, contain upper or lower case letters, ., -, _, and end with .xsd or .xml."
                      ),
                    modelObject=modelDocument,
                    filename=modelDocument.basename)

    if (modelDocument.type == ModelDocument.Type.SCHEMA
            and modelDocument.targetNamespace
            not in val.disclosureSystem.baseTaxonomyNamespaces
            and modelDocument.uri.startswith(val.modelXbrl.uriDir)):

        val.hasExtensionSchema = True
        # check schema contents types
        # 6.7.3 check namespace for standard authority
        targetNamespaceAuthority = UrlUtil.authority(
            modelDocument.targetNamespace)
        if targetNamespaceAuthority in val.disclosureSystem.standardAuthorities:
            val.modelXbrl.error(
                ("EFM.6.07.03", "GFM.1.03.03"),
                _("The target namespace, %(targetNamespace)s cannot have the same authority (%(targetNamespaceAuthority)s) as a standard "
                  "taxonomy, in %(schema)s.  Please change your target namespace."
                  ),
                edgarCode="fs-0703-Extension-Has-Standard-Namespace-Authority",
                modelObject=modelDocument,
                schema=modelDocument.basename,
                targetNamespace=modelDocument.targetNamespace,
                targetNamespaceAuthority=UrlUtil.authority(
                    modelDocument.targetNamespace, includeScheme=False))

        # 6.7.4 check namespace format
        if modelDocument.targetNamespace is None or not modelDocument.targetNamespace.startswith(
                "http://"):
            match = None
        else:
            targetNamespaceDate = modelDocument.targetNamespace[
                len(targetNamespaceAuthority):]
            match = targetNamespaceDatePattern.match(targetNamespaceDate)
        if match is not None:
            try:
                if match.lastindex == 3:
                    date = datetime.date(int(match.group(1)),
                                         int(match.group(2)),
                                         int(match.group(3)))
                elif match.lastindex == 6:
                    date = datetime.date(int(match.group(4)),
                                         int(match.group(5)),
                                         int(match.group(6)))
                else:
                    match = None
            except ValueError:
                match = None
        if match is None:
            val.modelXbrl.error(
                ("EFM.6.07.04", "GFM.1.03.04"),
                _("You did not adhere to the requirements for target namespace, for %(targetNamespace)s in %(schema)s.  "
                  "Please recheck your submission and adhere to the target namespace requirements."
                  ),
                edgarCode="cp-0704-Taxonomy-Valid-Target-Namespace",
                modelObject=modelDocument,
                schema=modelDocument.basename,
                targetNamespace=modelDocument.targetNamespace)
        elif val.fileNameDate and date > val.fileNameDate:
            val.modelXbrl.info(
                ("EFM.6.07.06", "GFM.1.03.06"),
                _("Warning: Taxonomy schema %(schema)s namespace %(targetNamespace)s has date later than document name date %(docNameDate)s"
                  ),
                modelObject=modelDocument,
                schema=modelDocument.basename,
                targetNamespace=modelDocument.targetNamespace,
                docNameDate=val.fileNameDate)

        if modelDocument.targetNamespace is not None:
            # 6.7.5 check prefix for _
            authority = UrlUtil.authority(modelDocument.targetNamespace)
            if not re.match(r"(http://|https://|ftp://|urn:)\w+", authority):
                val.modelXbrl.error(
                    ("EFM.6.07.05", "GFM.1.03.05"),
                    _("Taxonomy schema %(schema)s namespace %(targetNamespace)s must be a valid URI with a valid authority for the namespace."
                      ),
                    modelObject=modelDocument,
                    schema=modelDocument.basename,
                    targetNamespace=modelDocument.targetNamespace)
            # may be multiple prefixes for namespace
            prefixes = [
                (prefix if prefix is not None else "")
                for prefix, NS in modelDocument.xmlRootElement.nsmap.items()
                if NS == modelDocument.targetNamespace
            ]
            if not prefixes:
                prefix = None
                val.modelXbrl.error(
                    ("EFM.6.07.07", "GFM.1.03.07"),
                    _("The schema does not supply a prefix for %(targetNamespace)s without an underscore character, in file %(schema)s. "
                      "Please provide or change a prefix"),
                    edgarCode="du-0707-Recommended-Prefix-Disallowed",
                    modelObject=modelDocument,
                    schema=modelDocument.basename,
                    targetNamespace=modelDocument.targetNamespace)
            else:
                prefix = prefixes[0]
                if len(prefixes) > 1:
                    val.modelXbrl.error(
                        ("EFM.6.07.07", "GFM.1.03.07"),
                        _("The schema does not supply a prefix for %(targetNamespace)s without an underscore character, in file %(schema)s. "
                          "Please provide or change a prefix"),
                        edgarCode="du-0707-Recommended-Prefix-Disallowed",
                        modelObject=modelDocument,
                        schema=modelDocument.basename,
                        targetNamespace=modelDocument.targetNamespace,
                        prefix=", ".join(prefixes))
                elif "_" in prefix:
                    val.modelXbrl.error(
                        ("EFM.6.07.07", "GFM.1.03.07"),
                        _("The schema does not supply a prefix for %(targetNamespace)s without an underscore character, in file %(schema)s. "
                          "Please provide or change a prefix"),
                        edgarCode="du-0707-Recommended-Prefix-Disallowed",
                        modelObject=modelDocument,
                        schema=modelDocument.basename,
                        targetNamespace=modelDocument.targetNamespace,
                        prefix=prefix)

            for modelConcept in modelDocument.xmlRootElement.iterdescendants(
                    tag="{http://www.w3.org/2001/XMLSchema}element"):
                if isinstance(modelConcept, ModelConcept):
                    # 6.7.16 name not duplicated in standard taxonomies
                    name = modelConcept.get("name")
                    if name is None:
                        name = ""
                        if modelConcept.get("ref") is not None:
                            continue  # don't validate ref's here
                    for c in val.modelXbrl.nameConcepts.get(name, []):
                        if c.modelDocument != modelDocument:
                            if not c.modelDocument.uri.startswith(
                                    val.modelXbrl.uriDir):
                                val.modelXbrl.error(
                                    ("EFM.6.07.16", "GFM.1.03.18"),
                                    _("Your extension taxonomy contains an element, %(concept)s, which has the same name as an element in the base taxonomy, "
                                      "%(standardConcept)s.  Please ensure that this extension is appropriate and if so, please change the extension concept name."
                                      ),
                                    edgarCode=
                                    "cp-0716-Element-Name-Same-As-Base",
                                    modelObject=(modelConcept, c),
                                    concept=modelConcept.qname,
                                    standardSchema=c.modelDocument.basename,
                                    standardConcept=c.qname)

                    # 6.7.17 id properly formed
                    _id = modelConcept.id
                    requiredId = (prefix
                                  if prefix is not None else "") + "_" + name
                    if _id != requiredId:
                        val.modelXbrl.error(
                            ("EFM.6.07.17", "GFM.1.03.19"),
                            _("You did not adhere to the declarations for concepts by containing an 'id' attribute whose value begins with the recommended "
                              "namespace prefix of the taxonomy, followed by an underscore, followed by an element name, for the concept %(concept)s.  "
                              "Please recheck your submission."),
                            edgarCode="cp-0717-Element-Id",
                            modelObject=modelConcept,
                            concept=modelConcept.qname,
                            id=_id,
                            requiredId=requiredId)

                    # 6.7.18 nillable is true
                    nillable = modelConcept.get("nillable")
                    if nillable != "true" and modelConcept.isItem:
                        val.modelXbrl.error(
                            ("EFM.6.07.18", "GFM.1.03.20"),
                            _("Element %(concept)s is declared without a 'true' value for the nillable attribute.  Please set the value to 'true'."
                              ),
                            edgarCode="du-0718-Nillable-Not-True",
                            modelObject=modelConcept,
                            schema=modelDocument.basename,
                            concept=name,
                            nillable=nillable)

                    # 6.7.19 not tuple
                    if modelConcept.isTuple:
                        val.modelXbrl.error(
                            ("EFM.6.07.19", "GFM.1.03.21"),
                            _("You provided an extension concept which is a tuple, %(concept)s.  Please remove tuples and check your submission."
                              ),
                            edgarCode="cp-0719-No-Tuple-Element",
                            modelObject=modelConcept,
                            concept=modelConcept.qname)

                    # 6.7.20 no typed domain ref
                    if modelConcept.isTypedDimension:
                        val.modelXbrl.error(
                            ("EFM.6.07.20", "GFM.1.03.22"),
                            _("There is an xbrldt:typedDomainRef attribute on %(concept)s (%(typedDomainRef)s). Please remove it."
                              ),
                            edgarCode="du-0720-Typed-Domain-Ref-Disallowed",
                            modelObject=modelConcept,
                            concept=modelConcept.qname,
                            typedDomainRef=modelConcept.typedDomainElement.
                            qname if modelConcept.typedDomainElement
                            is not None else modelConcept.typedDomainRef)

                    # 6.7.21 abstract must be duration
                    isDuration = modelConcept.periodType == "duration"
                    if modelConcept.isAbstract and not isDuration:
                        val.modelXbrl.error(
                            ("EFM.6.07.21", "GFM.1.03.23"),
                            _("Element %(concept)s is declared as an abstract item with period type 'instant'.  Please change it to 'duration' or "
                              "make the element not abstract."),
                            edgarCode="du-0721-Abstract-Is-Instant",
                            modelObject=modelConcept,
                            schema=modelDocument.basename,
                            concept=modelConcept.qname)

                    # 6.7.22 abstract must be stringItemType
                    ''' removed SEC EFM v.17, Edgar release 10.4, and GFM 2011-04-08
                    if modelConcept.abstract == "true" and modelConcept.typeQname != XbrlConst. qnXbrliStringItemType:
                        val.modelXbrl.error(("EFM.6.07.22", "GFM.1.03.24"),
                            _("Concept %(concept)s  is abstract but type is not xbrli:stringItemType"),
                            modelObject=modelConcept, concept=modelConcept.qname)
					'''
                    substitutionGroupQname = modelConcept.substitutionGroupQname
                    # 6.7.23 Axis must be subs group dimension
                    if name.endswith("Axis") ^ (
                            substitutionGroupQname
                            == XbrlConst.qnXbrldtDimensionItem):
                        val.modelXbrl.error(
                            ("EFM.6.07.23", "GFM.1.03.25"),
                            _("The substitution group 'xbrldt:dimensionItem' is only consistent with an element name that ends with 'Axis'.  "
                              "Please change %(conceptLocalName)s or change the substitutionGroup."
                              ),
                            edgarCode="du-0723-Axis-Dimension-Name-Mismatch",
                            modelObject=modelConcept,
                            concept=modelConcept.qname,
                            conceptLocalName=modelConcept.qname.localName)

                    # 6.7.24 Table must be subs group hypercube
                    if name.endswith("Table") ^ (
                            substitutionGroupQname
                            == XbrlConst.qnXbrldtHypercubeItem):
                        val.modelXbrl.error(
                            ("EFM.6.07.24", "GFM.1.03.26"),
                            _("The substitution group 'xbrldt:hypercubeItem' is only allowed with an element name that ends with 'Table'.  "
                              "Please change %(conceptLocalName)s or change the substitutionGroup."
                              ),
                            edgarCode="du-0724-Table-Hypercube-Name-Mismatch",
                            modelObject=modelConcept,
                            schema=modelDocument.basename,
                            concept=modelConcept.qname,
                            conceptLocalName=modelConcept.qname.localName)

                    # 6.7.25 if neither hypercube or dimension, substitution group must be item
                    if substitutionGroupQname not in (
                            None, XbrlConst.qnXbrldtDimensionItem,
                            XbrlConst.qnXbrldtHypercubeItem,
                            XbrlConst.qnXbrliItem):
                        val.modelXbrl.error(
                            ("EFM.6.07.25", "GFM.1.03.27"),
                            _("The substitution group attribute value %(substitutionGroup)s of element %(conceptLocalName)s is not allowed.  "
                              "Please change it to one of 'xbrli:item', 'xbrldt:dimensionItem' or 'xbrldt:hypercubeItem'."
                              ),
                            edgarCode="du-0725-Substitution-Group-Custom",
                            modelObject=modelConcept,
                            concept=modelConcept.qname,
                            conceptLocalName=modelConcept.qname.localName,
                            substitutionGroup=modelConcept.
                            substitutionGroupQname)

                    # 6.7.26 Table must be subs group hypercube
                    if name.endswith(
                            "LineItems") and modelConcept.abstract != "true":
                        val.modelXbrl.error(
                            ("EFM.6.07.26", "GFM.1.03.28"),
                            _("The element %(conceptLocalName)s ends with 'LineItems' but is not abstract. Please change %(conceptLocalName)s or "
                              "the value of the 'abstract' attribute."),
                            edgarCode=
                            "du-0726-LineItems-Abstract-Name-Mismatch",
                            modelObject=modelConcept,
                            concept=modelConcept.qname,
                            conceptLocalName=modelConcept.qname.localName)

                    # 6.7.27 type domainMember must end with Domain or Member
                    conceptType = modelConcept.type
                    isDomainItemType = conceptType is not None and conceptType.isDomainItemType
                    endsWithDomainOrMember = name.endswith(
                        "Domain") or name.endswith("Member")
                    if isDomainItemType != endsWithDomainOrMember:
                        val.modelXbrl.error(
                            ("EFM.6.07.27", "GFM.1.03.29"),
                            _("The type 'us-types:domainItemType' is only allowed with an element name that ends with 'Domain' or 'Member'.  "
                              "Please change %(conceptLocalName)s or change the type."
                              ),
                            edgarCode="du-0727-Domain-Type-Name-Mismatch",
                            modelObject=modelConcept,
                            concept=modelConcept.qname,
                            conceptLocalName=modelConcept.qname.localName)

                    # 6.7.28 domainItemType must be duration
                    if isDomainItemType and not isDuration:
                        val.modelXbrl.error(
                            ("EFM.6.07.28", "GFM.1.03.30"),
                            _("Element %(conceptLocalName)s is declared as a us-types:domainItemType with period type 'instant'.  "
                              "Please change it to 'duration' or change the item type."
                              ),
                            edgarCode="du-0728-Domain-Member-Is-Instant",
                            modelObject=modelConcept,
                            concept=modelConcept.qname,
                            conceptLocalName=modelConcept.qname.localName)

                    #6.7.31 (version 27) fractions
                    if modelConcept.isFraction:
                        val.modelXbrl.error(
                            "EFM.6.07.31",
                            _("Element %(concept)s is declared as a fraction item type.  Change or remove the declaration."
                              ),
                            edgarCode="du-0731-Fraction-Item-Type",
                            modelObject=modelConcept,
                            concept=modelConcept.qname)

                    #6.7.32 (version 27) instant non numeric
                    if modelConcept.isItem and (not modelConcept.isNumeric
                                                and not isDuration
                                                and not modelConcept.isAbstract
                                                and not isDomainItemType):
                        val.modelXbrl.error(
                            "EFM.6.07.32",
                            _("Declaration of element %(concept)s in %(schema)s must have xbrli:periodType of 'duration' because its base type is not numeric."
                              ),
                            edgarCode="rq-0732-Nonnnumeric-Must-Be-Duration",
                            modelObject=modelConcept,
                            schema=modelDocument.basename,
                            concept=modelConcept.qname)

                    # 6.8.5 semantic check, check LC3 name
                    if name:
                        if not name[0].isupper():
                            val.modelXbrl.log(
                                "ERROR-SEMANTIC", ("EFM.6.08.05.firstLetter",
                                                   "GFM.2.03.05.firstLetter"),
                                _("Concept %(concept)s name must start with a capital letter"
                                  ),
                                modelObject=modelConcept,
                                concept=modelConcept.qname)
                        if namePattern.search(name):
                            val.modelXbrl.log(
                                "ERROR-SEMANTIC",
                                ("EFM.6.08.05.disallowedCharacter",
                                 "GFM.2.03.05.disallowedCharacter"),
                                _("Concept %(concept)s has disallowed name character"
                                  ),
                                modelObject=modelConcept,
                                concept=modelConcept.qname)
                        if len(name) > 200:
                            val.modelXbrl.log(
                                "ERROR-SEMANTIC",
                                "EFM.6.08.05.nameLength",
                                _("Concept %(concept)s name length %(namelength)s exceeds 200 characters"
                                  ),
                                modelObject=modelConcept,
                                concept=modelConcept.qname,
                                namelength=len(name))

                    if isEFM:
                        label = modelConcept.label(lang="en-US",
                                                   fallbackToQname=False)
                        if label:
                            # allow Joe's Bar, N.A.  to be JoesBarNA -- remove ', allow A. as not article "a"
                            lc3name = ''.join(
                                re.sub(r"['.-]", "", (
                                    w[0] or w[2] or w[3] or w[4])).title()
                                for w in re.findall(
                                    r"((\w+')+\w+)|(A[.-])|([.-]A(?=\W|$))|(\w+)",
                                    label
                                )  # EFM implies this should allow - and . re.findall(r"[\w\-\.]+", label)
                                if w[4].lower() not in ("the", "a", "an"))
                            if not (name == lc3name or
                                    (name and lc3name and lc3name[0].isdigit()
                                     and name[1:] == lc3name and
                                     (name[0].isalpha() or name[0] == '_'))):
                                val.modelXbrl.log(
                                    "WARNING-SEMANTIC",
                                    "EFM.6.08.05.LC3",
                                    _("Concept %(concept)s should match expected LC3 composition %(lc3name)s"
                                      ),
                                    modelObject=modelConcept,
                                    concept=modelConcept.qname,
                                    lc3name=lc3name)

                    if conceptType is not None:
                        # 6.8.6 semantic check
                        if not isDomainItemType and conceptType.qname != XbrlConst.qnXbrliDurationItemType:
                            nameProblems = nonDomainItemNameProblemPattern.findall(
                                name)
                            if any(
                                    any(t) for t in nameProblems
                            ):  # list of tuples with possibly nonempty strings
                                val.modelXbrl.log(
                                    "WARNING-SEMANTIC",
                                    ("EFM.6.08.06", "GFM.2.03.06"),
                                    _("Concept %(concept)s should not contain company or period information, found: %(matches)s"
                                      ),
                                    modelObject=modelConcept,
                                    concept=modelConcept.qname,
                                    matches=", ".join(''.join(t)
                                                      for t in nameProblems))

                        if conceptType.qname == XbrlConst.qnXbrliMonetaryItemType:
                            if not modelConcept.balance:
                                # 6.8.11 may not appear on a income or balance statement
                                if any(
                                        linkroleDefinitionBalanceIncomeSheet.
                                        match(roleType.definition)
                                        for rel in val.modelXbrl.
                                        relationshipSet(XbrlConst.parentChild).
                                        toModelObject(modelConcept)
                                        for roleType in val.modelXbrl.
                                        roleTypes.get(rel.linkrole, ())):
                                    val.modelXbrl.log(
                                        "ERROR-SEMANTIC",
                                        ("EFM.6.08.11", "GFM.2.03.11"),
                                        _("Concept %(concept)s must have a balance because it appears in a statement of income or balance sheet"
                                          ),
                                        modelObject=modelConcept,
                                        concept=modelConcept.qname)
                                # 6.11.5 semantic check, must have a documentation label
                                stdLabel = modelConcept.label(
                                    lang="en-US", fallbackToQname=False)
                                defLabel = modelConcept.label(
                                    preferredLabel=XbrlConst.
                                    documentationLabel,
                                    lang="en-US",
                                    fallbackToQname=False)
                                if not defLabel or (  # want different words than std label
                                        stdLabel
                                        and re.findall(r"\w+", stdLabel)
                                        == re.findall(r"\w+", defLabel)):
                                    val.modelXbrl.log(
                                        "ERROR-SEMANTIC",
                                        ("EFM.6.11.05", "GFM.2.04.04"),
                                        _("Concept %(concept)s is monetary without a balance and must have a documentation label that disambiguates its sign"
                                          ),
                                        modelObject=modelConcept,
                                        concept=modelConcept.qname)

                        # 6.8.16 semantic check
                        if conceptType.qname == XbrlConst.qnXbrliDateItemType and modelConcept.periodType != "duration":
                            val.modelXbrl.log(
                                "ERROR-SEMANTIC",
                                ("EFM.6.08.16", "GFM.2.03.16"),
                                _("Concept %(concept)s of type xbrli:dateItemType must have periodType duration"
                                  ),
                                modelObject=modelConcept,
                                concept=modelConcept.qname)

                        # 6.8.17 semantic check
                        if conceptType.qname == XbrlConst.qnXbrliStringItemType and modelConcept.periodType != "duration":
                            val.modelXbrl.log(
                                "ERROR-SEMANTIC",
                                ("EFM.6.08.17", "GFM.2.03.17"),
                                _("Concept %(concept)s of type xbrli:stringItemType must have periodType duration"
                                  ),
                                modelObject=modelConcept,
                                concept=modelConcept.qname)

        # 6.7.8 check for embedded linkbase
        for e in modelDocument.xmlRootElement.iterdescendants(
                tag="{http://www.xbrl.org/2003/linkbase}linkbase"):
            if isinstance(e, ModelObject):
                val.modelXbrl.error(
                    ("EFM.6.07.08", "GFM.1.03.08"),
                    _("Your filing contained embedded linkbases in %(schema)s.  Please recheck your submission and remove all embedded linkbases."
                      ),
                    edgarCode="cp-0708-No-Embedded-Linkbases",
                    modelObject=e,
                    schema=modelDocument.basename)
                break

        requiredUsedOns = {
            XbrlConst.qnLinkPresentationLink, XbrlConst.qnLinkCalculationLink,
            XbrlConst.qnLinkDefinitionLink
        }

        standardUsedOns = {
            XbrlConst.qnLinkLabel,
            XbrlConst.qnLinkReference,
            XbrlConst.qnLinkDefinitionArc,
            XbrlConst.qnLinkCalculationArc,
            XbrlConst.qnLinkPresentationArc,
            XbrlConst.qnLinkLabelArc,
            XbrlConst.qnLinkReferenceArc,
            # per WH, private footnote arc and footnore resource roles are not allowed
            XbrlConst.qnLinkFootnoteArc,
            XbrlConst.qnLinkFootnote,
        }

        # 6.7.9 role types authority
        for e in modelDocument.xmlRootElement.iterdescendants(
                tag="{http://www.xbrl.org/2003/linkbase}roleType"):
            if isinstance(e, ModelObject):
                roleURI = e.get("roleURI")
                if targetNamespaceAuthority != UrlUtil.authority(roleURI):
                    val.modelXbrl.error(
                        ("EFM.6.07.09", "GFM.1.03.09"),
                        _("Role %(roleType)s does not begin with %(targetNamespace)s's scheme and authority. "
                          "Please change the role URI or target namespace URI."
                          ),
                        edgarCode="du-0709-Role-Namespace-Mismatch",
                        modelObject=e,
                        roleType=roleURI,
                        targetNamespaceAuthority=targetNamespaceAuthority,
                        targetNamespace=modelDocument.targetNamespace)
                # 6.7.9 end with .../role/lc3 name
                if not roleTypePattern.match(roleURI):
                    val.modelXbrl.warning(
                        ("EFM.6.07.09.roleEnding", "GFM.1.03.09"),
                        "RoleType %(roleType)s should end with /role/{LC3name}",
                        modelObject=e,
                        roleType=roleURI)

                # 6.7.10 only one role type declaration in DTS
                modelRoleTypes = val.modelXbrl.roleTypes.get(roleURI)
                if modelRoleTypes is not None:
                    modelRoleType = modelRoleTypes[0]
                    definition = modelRoleType.definitionNotStripped
                    usedOns = modelRoleType.usedOns
                    if len(modelRoleTypes) == 1:
                        # 6.7.11 used on's for pre, cal, def if any has a used on
                        if not usedOns.isdisjoint(requiredUsedOns) and len(
                                requiredUsedOns - usedOns) > 0:
                            val.modelXbrl.error(
                                ("EFM.6.07.11", "GFM.1.03.11"),
                                _("The role %(roleType)s did not provide a usedOn element for all three link types (presentation, "
                                  "calculation and definition), missing %(usedOn)s. Change the declaration to be for all three types of link, and resubmit."
                                  ),
                                edgarCode=
                                "du-0711-Role-Type-Declaration-Incomplete",
                                modelObject=e,
                                roleType=roleURI,
                                usedOn=requiredUsedOns - usedOns)

                        # 6.7.12 definition match pattern
                        if (val.disclosureSystem.roleDefinitionPattern
                                is not None and
                            (definition is None or not val.disclosureSystem.
                             roleDefinitionPattern.match(definition))):
                            val.modelXbrl.error(
                                ("EFM.6.07.12", "GFM.1.03.12-14"),
                                _("The definition '%(definition)s' of role %(roleType)s does not match the expected format. "
                                  "Please check that the definition matches {number} - {type} - {text}."
                                  ),
                                edgarCode="rq-0712-Role-Definition-Mismatch",
                                modelObject=e,
                                roleType=roleURI,
                                definition=(definition or ""))

                    if usedOns & standardUsedOns:  # semantics check
                        val.modelXbrl.log(
                            "ERROR-SEMANTIC", ("EFM.6.08.03", "GFM.2.03.03"),
                            _("RoleType %(roleuri)s is defined using role types already defined by standard roles for: %(qnames)s"
                              ),
                            modelObject=e,
                            roleuri=roleURI,
                            qnames=', '.join(
                                str(qn) for qn in usedOns & standardUsedOns))

        # 6.7.13 arcrole types authority
        for e in modelDocument.xmlRootElement.iterdescendants(
                tag="{http://www.xbrl.org/2003/linkbase}arcroleType"):
            if isinstance(e, ModelObject):
                arcroleURI = e.get("arcroleURI")
                if targetNamespaceAuthority != UrlUtil.authority(arcroleURI):
                    val.modelXbrl.error(
                        ("EFM.6.07.13", "GFM.1.03.15"),
                        _("Relationship role %(arcroleType)s does not begin with %(targetNamespace)s's scheme and authority.  "
                          "Please change the relationship role URI or target namespace URI."
                          ),
                        edgarCode="du-0713-Arcrole-Namespace-Mismatch",
                        modelObject=e,
                        arcroleType=arcroleURI,
                        targetNamespaceAuthority=targetNamespaceAuthority,
                        targetNamespace=modelDocument.targetNamespace)
                # 6.7.13 end with .../arcrole/lc3 name
                if not arcroleTypePattern.match(arcroleURI):
                    val.modelXbrl.warning(
                        ("EFM.6.07.13.arcroleEnding", "GFM.1.03.15"),
                        _("ArcroleType %(arcroleType)s should end with /arcrole/{LC3name}"
                          ),
                        modelObject=e,
                        arcroleType=arcroleURI)

                # 6.7.15 definition match pattern
                modelRoleTypes = val.modelXbrl.arcroleTypes[arcroleURI]
                definition = modelRoleTypes[0].definition
                if definition is None or not arcroleDefinitionPattern.match(
                        definition):
                    val.modelXbrl.error(
                        ("EFM.6.07.15", "GFM.1.03.17"),
                        _("Relationship role declaration %(arcroleType)s is missing a definition.  Please provide a definition."
                          ),
                        edgarCode="du-0715-Arcrole-Definition-Missing",
                        modelObject=e,
                        arcroleType=arcroleURI)

                # semantic checks
                usedOns = modelRoleTypes[0].usedOns
                if usedOns & standardUsedOns:  # semantics check
                    val.modelXbrl.log(
                        "ERROR-SEMANTIC", ("EFM.6.08.03", "GFM.2.03.03"),
                        _("ArcroleType %(arcroleuri)s is defined using role types already defined by standard arcroles for: %(qnames)s"
                          ),
                        modelObject=e,
                        arcroleuri=arcroleURI,
                        qnames=', '.join(
                            str(qn) for qn in usedOns & standardUsedOns))

        #6.3.3 filename check
        m = re.match(r"^\w+-([12][0-9]{3}[01][0-9][0-3][0-9]).xsd$",
                     modelDocument.basename)
        if m:
            try:  # check date value
                datetime.datetime.strptime(m.group(1), "%Y%m%d").date()
                # date and format are ok, check "should" part of 6.3.3
                if val.fileNameBasePart:
                    expectedFilename = "{0}-{1}.xsd".format(
                        val.fileNameBasePart, val.fileNameDatePart)
                    if modelDocument.basename != expectedFilename:
                        val.modelXbrl.log(
                            "WARNING-SEMANTIC", ("EFM.6.03.03.matchInstance",
                                                 "GFM.1.01.01.matchInstance"),
                            _('Schema file name warning: %(filename)s, should match %(expectedFilename)s'
                              ),
                            modelObject=modelDocument,
                            filename=modelDocument.basename,
                            expectedFilename=expectedFilename)
            except ValueError:
                val.modelXbrl.error(
                    (val.EFM60303, "GFM.1.01.01"),
                    _('Invalid schema file base name part (date) in "{base}-{yyyymmdd}.xsd": %(filename)s'
                      ),
                    modelObject=modelDocument,
                    filename=modelDocument.basename,
                    messageCodes=("EFM.6.03.03", "EFM.6.23.01", "GFM.1.01.01"))
        else:
            val.modelXbrl.error(
                (val.EFM60303, "GFM.1.01.01"),
                _('Invalid schema file name, must match "{base}-{yyyymmdd}.xsd": %(filename)s'
                  ),
                modelObject=modelDocument,
                filename=modelDocument.basename,
                messageCodes=("EFM.6.03.03", "EFM.6.23.01", "GFM.1.01.01"))

    elif modelDocument.type == ModelDocument.Type.LINKBASE:
        # if it is part of the submission (in same directory) check name
        labelRels = None
        if modelDocument.filepath.startswith(
                val.modelXbrl.modelDocument.filepathdir):
            #6.3.3 filename check
            extLinkElt = XmlUtil.descendant(
                modelDocument.xmlRootElement, XbrlConst.link, "*",
                "{http://www.w3.org/1999/xlink}type", "extended")
            if extLinkElt is None:  # no ext link element
                val.modelXbrl.error(
                    (val.EFM60303 + ".noLinkElement",
                     "GFM.1.01.01.noLinkElement"),
                    _('Invalid linkbase file name: %(filename)s, has no extended link element, cannot determine link type.'
                      ),
                    modelObject=modelDocument,
                    filename=modelDocument.basename,
                    messageCodes=("EFM.6.03.03.noLinkElement",
                                  "EFM.6.23.01.noLinkElement",
                                  "GFM.1.01.01.noLinkElement"))
            elif extLinkElt.localName not in extLinkEltFileNameEnding:
                val.modelXbrl.error(
                    "EFM.6.03.02",
                    _('Invalid linkbase link element %(linkElement)s in %(filename)s'
                      ),
                    modelObject=modelDocument,
                    linkElement=extLinkElt.localName,
                    filename=modelDocument.basename)
            else:
                m = re.match(
                    r"^\w+-([12][0-9]{3}[01][0-9][0-3][0-9])(_[a-z]{3}).xml$",
                    modelDocument.basename)
                expectedSuffix = extLinkEltFileNameEnding[extLinkElt.localName]
                if m and m.group(2) == expectedSuffix:
                    try:  # check date value
                        datetime.datetime.strptime(m.group(1), "%Y%m%d").date()
                        # date and format are ok, check "should" part of 6.3.3
                        if val.fileNameBasePart:
                            expectedFilename = "{0}-{1}{2}.xml".format(
                                val.fileNameBasePart, val.fileNameDatePart,
                                expectedSuffix)
                            if modelDocument.basename != expectedFilename:
                                val.modelXbrl.log(
                                    "WARNING-SEMANTIC",
                                    ("EFM.6.03.03.matchInstance",
                                     "GFM.1.01.01.matchInstance"),
                                    _('Linkbase name warning: %(filename)s should match %(expectedFilename)s'
                                      ),
                                    modelObject=modelDocument,
                                    filename=modelDocument.basename,
                                    expectedFilename=expectedFilename)
                    except ValueError:
                        val.modelXbrl.error(
                            (val.EFM60303, "GFM.1.01.01"),
                            _('Invalid linkbase base file name part (date) in "{base}-{yyyymmdd}_{suffix}.xml": %(filename)s'
                              ),
                            modelObject=modelDocument,
                            filename=modelDocument.basename,
                            messageCodes=("EFM.6.03.03", "EFM.6.23.01",
                                          "GFM.1.01.01"))
                else:
                    val.modelXbrl.error(
                        (val.EFM60303, "GFM.1.01.01"),
                        _('Invalid linkbase name, must match "{base}-{yyyymmdd}%(expectedSuffix)s.xml": %(filename)s'
                          ),
                        modelObject=modelDocument,
                        filename=modelDocument.basename,
                        expectedSuffix=expectedSuffix,
                        messageCodes=("EFM.6.03.03", "EFM.6.23.01",
                                      "GFM.1.01.01"))
                if extLinkElt.localName == "labelLink":
                    if labelRels is None:
                        labelRels = val.modelXbrl.relationshipSet(
                            XbrlConst.conceptLabel)
                    for labelElt in XmlUtil.children(extLinkElt,
                                                     XbrlConst.link, "label"):
                        # 6.10.9
                        if XbrlConst.isNumericRole(labelElt.role):
                            for rel in labelRels.toModelObject(labelElt):
                                if rel.fromModelObject is not None and not rel.fromModelObject.isNumeric:
                                    val.modelXbrl.error(
                                        "EFM.6.10.09",
                                        _("Non-numeric element %(concept)s has a label role for numeric elements: %(role)s. "
                                          "Please change the role attribute."),
                                        edgarCode="du-1009-Numeric-Label-Role",
                                        modelObject=(labelElt,
                                                     rel.fromModelObject),
                                        concept=rel.fromModelObject.qname,
                                        role=labelElt.role)
Example #37
0
 def relationshipSetElement(self):
     return XmlUtil.child(self, XbrlConst.verrels, "relationshipSet")
Example #38
0
    def open(self, reloadCache=False):
        if not self.isOpen:
            if (self.isZip or self.isTarGz or self.isEis or self.isXfd or self.isRss or self.isInstalledTaxonomyPackage) and self.cntlr:
                self.basefile = self.cntlr.webCache.getfilename(self.url, reload=reloadCache)
            else:
                self.basefile = self.url
            self.baseurl = self.url # url gets changed by selection
            if not self.basefile:
                return  # an error should have been logged
            if self.isZip:
                try:
                    self.fs = zipfile.ZipFile(openFileStream(self.cntlr, self.basefile, 'rb'), mode="r")
                    self.isOpen = True
                except EnvironmentError as err:
                    self.logError(err)
                    pass
            elif self.isTarGz:
                try:
                    self.fs = tarfile.open(self.basefile, "r:gz")
                    self.isOpen = True
                except EnvironmentError as err:
                    self.logError(err)
                    pass
            elif self.isEis:
                # check first line of file
                buf = b''
                try:
                    file = open(self.basefile, 'rb')
                    more = True
                    while more:
                        l = file.read(8)
                        if len(l) < 8:
                            break
                        if len(buf) == 0 and l.startswith(b"<?xml "): # not compressed
                            buf = l + file.read()  # not compressed
                            break
                        compressedBytes = file.read( struct.unpack(">L", l[0:4])[0])
                        if len(compressedBytes) <= 0:
                            break
                        buf += zlib.decompress(compressedBytes)
                    file.close()
                except EnvironmentError as err:
                    self.logError(err)
                    pass
                #uncomment to save for debugging
                #with open("c:/temp/test.xml", "wb") as f:
                #    f.write(buf)
                
                if buf.startswith(b"<?xml "):
                    try:
                        # must strip encoding
                        str = buf.decode(XmlUtil.encoding(buf))
                        endEncoding = str.index("?>", 0, 128)
                        if endEncoding > 0:
                            str = str[endEncoding+2:]
                        file = io.StringIO(initial_value=str)
                        parser = etree.XMLParser(recover=True, huge_tree=True)
                        self.eisDocument = etree.parse(file, parser=parser)
                        file.close()
                        self.isOpen = True
                    except EnvironmentError as err:
                        self.logError(err)
                        return # provide error message later
                    except etree.LxmlError as err:
                        self.logError(err)
                        return # provide error message later
                
            elif self.isXfd:
                # check first line of file
                file = open(self.basefile, 'rb')
                firstline = file.readline()
                if firstline.startswith(b"application/x-xfdl;content-encoding=\"asc-gzip\""):
                    # file has been gzipped
                    base64input = file.read(-1)
                    file.close();
                    file = None;
    
                    fb = base64.b64decode(base64input)
                    ungzippedBytes = b""
                    totalLenUncompr = 0
                    i = 0
                    while i < len(fb):
                        lenCompr = fb[i + 0] * 256 + fb[i + 1]
                        lenUncomp = fb[i + 2] * 256 + fb[i + 3]
                        lenRead = 0
                        totalLenUncompr += lenUncomp

                        gzchunk = (bytes((31,139,8,0)) + fb[i:i+lenCompr])
                        try:
                            with gzip.GzipFile(fileobj=io.BytesIO(gzchunk)) as gf:
                                while True:
                                    readSize = min(16384, lenUncomp - lenRead)
                                    readBytes = gf.read(size=readSize)
                                    lenRead += len(readBytes)
                                    ungzippedBytes += readBytes
                                    if len(readBytes) == 0 or (lenUncomp - lenRead) <= 0:
                                        break
                        except IOError as err:
                            pass # provide error message later

                        i += lenCompr + 4
                    #for learning the content of xfd file, uncomment this:
                    #with open("c:\\temp\\test.xml", "wb") as fh:
                    #    fh.write(ungzippedBytes)
                    file = io.StringIO(initial_value=ungzippedBytes.decode("utf-8"))
                else:
                    # position to start of file
                    file.seek(0,io.SEEK_SET)
                    
                try:
                    self.xfdDocument = etree.parse(file)
                    file.close()
                    self.isOpen = True
                except EnvironmentError as err:
                    self.logError(err)
                    return # provide error message later
                except etree.LxmlError as err:
                    self.logError(err)
                    return # provide error message later
                
            elif self.isRss:
                try:
                    self.rssDocument = etree.parse(self.basefile)
                    self.isOpen = True
                except EnvironmentError as err:
                    self.logError(err)
                    return # provide error message later
                except etree.LxmlError as err:
                    self.logError(err)
                    return # provide error message later
            
            elif self.isInstalledTaxonomyPackage:
                self.isOpen = True
                # load mappings
                self.loadTaxonomyPackageMappings()
Example #39
0
    def view(self):
        self.blockSelectEvent = 1
        self.blockViewModelObject = 0
        self.tag_has = defaultdict(list)  # temporary until Tk 8.6
        # relationship set based on linkrole parameter, to determine applicable linkroles
        relationshipSet = self.modelXbrl.relationshipSet(
            self.arcrole, self.linkrole, self.linkqname, self.arcqname)
        if not relationshipSet:
            self.modelXbrl.modelManager.addToLog(
                _("no relationships for {0}").format(self.arcrole))
            return False
        # consider facts in the relationshipSet (only)
        contexts = set()
        self.conceptFacts = defaultdict(list)
        if self.linkrole and hasattr(
                self.modelXbrl.roleTypes[self.linkrole][0], "_tableFacts"):
            for fact in self.modelXbrl.roleTypes[self.linkrole][0]._tableFacts:
                self.conceptFacts[fact.qname].append(fact)
                if fact.context is not None:
                    contexts.add(fact.context)
        else:
            for fact in self.modelXbrl.facts:
                if relationshipSet.fromModelObject(
                        fact.concept) or relationshipSet.toModelObject(
                            fact.concept):
                    self.conceptFacts[fact.qname].append(fact)
                    if fact.context is not None:
                        contexts.add(fact.context)
        # sort contexts by period
        self.periodContexts = defaultdict(set)
        contextStartDatetimes = {}
        ignoreDims = self.ignoreDims.get()
        showDimDefaults = self.showDimDefaults.get()
        for context in contexts:
            if ignoreDims:
                if context.isForeverPeriod:
                    contextkey = datetime.datetime(datetime.MINYEAR, 1, 1)
                else:
                    contextkey = context.endDatetime
            else:
                if context.isForeverPeriod:
                    contextkey = "forever"
                else:
                    contextkey = (
                        context.endDatetime -
                        datetime.timedelta(days=1)).strftime("%Y-%m-%d")

                values = []
                dims = context.qnameDims
                if len(dims) > 0:
                    for dimQname in sorted(dims.keys(), key=lambda d: str(d)):
                        dimvalue = dims[dimQname]
                        if dimvalue.isExplicit:
                            values.append(
                                dimvalue.member.
                                label(self.labelrole, lang=self.lang
                                      ) if dimvalue.member is not None else
                                str(dimvalue.memberQname))
                        else:
                            values.append(
                                XmlUtil.innerText(dimvalue.typedMember))

                nonDimensions = context.nonDimValues(
                    "segment") + context.nonDimValues("scenario")
                if len(nonDimensions) > 0:
                    for element in sorted(nonDimensions,
                                          key=lambda e: e.localName):
                        values.append(XmlUtil.innerText(element))

                if len(values) > 0:

                    contextkey += " - " + ', '.join(values)

            objectId = context.objectId()
            self.periodContexts[contextkey].add(objectId)
            if context.isStartEndPeriod:
                contextStartDatetimes[objectId] = context.startDatetime
        self.periodKeys = list(self.periodContexts.keys())
        self.periodKeys.sort()
        # set up treeView widget and tabbed pane
        self.treeView.column("#0", width=300, anchor="w")
        self.treeView.heading("#0", text="Concept")
        columnIds = []
        columnIdHeadings = []
        self.contextColId = {}
        self.startdatetimeColId = {}
        self.numCols = 1
        for periodKey in self.periodKeys:
            colId = "#{0}".format(self.numCols)
            columnIds.append(colId)
            columnIdHeadings.append((colId, periodKey))
            for contextId in self.periodContexts[periodKey]:
                self.contextColId[contextId] = colId
                if contextId in contextStartDatetimes:
                    self.startdatetimeColId[
                        contextStartDatetimes[contextId]] = colId
            self.numCols += 1
        self.treeView["columns"] = columnIds
        for colId, colHeading in columnIdHeadings:
            self.treeView.column(colId, width=100, anchor="w")
            if ignoreDims:
                if colHeading.year == datetime.MINYEAR:
                    date = "forever"
                else:
                    date = (colHeading -
                            datetime.timedelta(days=1)).strftime("%Y-%m-%d")
                self.treeView.heading(colId, text=date)
            else:
                self.treeView.heading(colId, text=colHeading)

        # fact rendering
        self.clearTreeView()
        self.rowColFactId = {}
        # root node for tree view
        self.id = 1
        # sort URIs by definition
        linkroleUris = []
        relationshipSet = self.modelXbrl.relationshipSet(
            self.arcrole, self.linkrole, self.linkqname, self.arcqname)
        if self.linkrole:
            roleType = self.modelXbrl.roleTypes[self.linkrole][0]
            linkroleUris.append(
                ((roleType.genLabel(lang=self.lang, strip=True)
                  or roleType.definition
                  or linkroleUri), self.linkrole, roleType.objectId(self.id)))
            self.id += 1
        else:
            for linkroleUri in relationshipSet.linkRoleUris:
                modelRoleTypes = self.modelXbrl.roleTypes.get(linkroleUri)
                if modelRoleTypes:
                    roledefinition = (modelRoleTypes[0].genLabel(
                        lang=self.lang, strip=True)
                                      or modelRoleTypes[0].definition
                                      or linkroleUri)
                    roleId = modelRoleTypes[0].objectId(self.id)
                else:
                    roledefinition = linkroleUri
                    roleId = "node{0}".format(self.id)
                self.id += 1
                linkroleUris.append((roledefinition, linkroleUri, roleId))
            linkroleUris.sort()
        # for each URI in definition order
        for linkroleUriTuple in linkroleUris:
            linknode = self.treeView.insert("",
                                            "end",
                                            linkroleUriTuple[2],
                                            text=linkroleUriTuple[0],
                                            tags=("ELR", ))
            linkRelationshipSet = self.modelXbrl.relationshipSet(
                self.arcrole, linkroleUriTuple[1], self.linkqname,
                self.arcqname)
            for rootConcept in linkRelationshipSet.rootConcepts:
                node = self.viewConcept(rootConcept, rootConcept, "",
                                        self.labelrole, linknode, 1,
                                        linkRelationshipSet, set())

        if self.expandAllOnFirstDisplay:
            self.expandAll()

        return True
Example #40
0
 def file(self, filepath, binary=False, stripDeclaration=False, encoding=None):
     ''' 
         for text, return a tuple of (open file handle, encoding)
         for binary, return a tuple of (open file handle, )
     '''
     archiveFileSource = self.fileSourceContainingFilepath(filepath)
     if archiveFileSource is not None:
         if filepath.startswith(archiveFileSource.basefile):
             archiveFileName = filepath[len(archiveFileSource.basefile) + 1:]
         else: # filepath.startswith(self.baseurl)
             archiveFileName = filepath[len(archiveFileSource.baseurl) + 1:]
         if archiveFileSource.isZip:
             try:
                 if archiveFileSource.isZipBackslashed:
                     f = archiveFileName.replace("/", "\\")
                 else:
                     f = archiveFileName.replace("\\","/")
                 b = archiveFileSource.fs.read(f)
                 if binary:
                     return (io.BytesIO(b), )
                 if encoding is None:
                     encoding = XmlUtil.encoding(b)
                 if stripDeclaration:
                     b = stripDeclarationBytes(b)
                 return (FileNamedTextIOWrapper(filepath, io.BytesIO(b), encoding=encoding), 
                         encoding)
             except KeyError:
                 raise ArchiveFileIOError(self, errno.ENOENT, archiveFileName)
         elif archiveFileSource.isTarGz:
             try:
                 fh = archiveFileSource.fs.extractfile(archiveFileName)
                 b = fh.read()
                 fh.close() # doesn't seem to close properly using a with construct
                 if binary:
                     return (io.BytesIO(b), )
                 if encoding is None:
                     encoding = XmlUtil.encoding(b)
                 if stripDeclaration:
                     b = stripDeclarationBytes(b)
                 return (FileNamedTextIOWrapper(filepath, io.BytesIO(b), encoding=encoding), 
                         encoding)
             except KeyError:
                 raise ArchiveFileIOError(self, archiveFileName)
         elif archiveFileSource.isEis:
             for docElt in self.eisDocument.iter(tag="{http://www.sec.gov/edgar/common}document"):
                 outfn = docElt.findtext("{http://www.sec.gov/edgar/common}conformedName")
                 if outfn == archiveFileName:
                     b64data = docElt.findtext("{http://www.sec.gov/edgar/common}contents")
                     if b64data:
                         b = base64.b64decode(b64data.encode("latin-1"))
                         # remove BOM codes if present
                         if len(b) > 3 and b[0] == 239 and b[1] == 187 and b[2] == 191:
                             start = 3;
                             length = len(b) - 3;
                             b = b[start:start + length]
                         else:
                             start = 0;
                             length = len(b);
                         if binary:
                             return (io.BytesIO(b), )
                         if encoding is None:
                             encoding = XmlUtil.encoding(b, default="latin-1")
                         return (io.TextIOWrapper(io.BytesIO(b), encoding=encoding), 
                                 encoding)
             raise ArchiveFileIOError(self, errno.ENOENT, archiveFileName)
         elif archiveFileSource.isXfd:
             for data in archiveFileSource.xfdDocument.iter(tag="data"):
                 outfn = data.findtext("filename")
                 if outfn == archiveFileName:
                     b64data = data.findtext("mimedata")
                     if b64data:
                         b = base64.b64decode(b64data.encode("latin-1"))
                         # remove BOM codes if present
                         if len(b) > 3 and b[0] == 239 and b[1] == 187 and b[2] == 191:
                             start = 3;
                             length = len(b) - 3;
                             b = b[start:start + length]
                         else:
                             start = 0;
                             length = len(b);
                         if binary:
                             return (io.BytesIO(b), )
                         if encoding is None:
                             encoding = XmlUtil.encoding(b, default="latin-1")
                         return (io.TextIOWrapper(io.BytesIO(b), encoding=encoding), 
                                 encoding)
             raise ArchiveFileIOError(self, errno.ENOENT, archiveFileName)
         elif archiveFileSource.isInstalledTaxonomyPackage:
             # remove TAXONOMY_PACKAGE_FILE_NAME from file path
             if filepath.startswith(archiveFileSource.basefile):
                 l = len(archiveFileSource.basefile)
                 for f in TAXONOMY_PACKAGE_FILE_NAMES:
                     if filepath[l - len(f):l] == f:
                         filepath = filepath[0:l - len(f) - 1] + filepath[l:]
                         break
     for pluginMethod in pluginClassMethods("FileSource.File"): #custom overrides for decription, etc
         fileResult = pluginMethod(self.cntlr, filepath, binary, stripDeclaration)
         if fileResult is not None:
             return fileResult
     if binary:
         return (openFileStream(self.cntlr, filepath, 'rb'), )
     elif encoding:
         return (openFileStream(self.cntlr, filepath, 'rt', encoding=encoding), )
     else:
         return openXmlFileStream(self.cntlr, filepath, stripDeclaration)
Example #41
0
 def dir(self):
     self.open()
     if not self.isOpen:
         return None
     elif self.filesDir is not None:
         return self.filesDir
     elif self.isZip:
         files = []
         for zipinfo in self.fs.infolist():
             f = zipinfo.filename
             if '\\' in f:
                 self.isZipBackslashed = True
                 f = f.replace("\\", "/")
             files.append(f)
         self.filesDir = files
     elif self.isTarGz:
         self.filesDir = self.fs.getnames()
     elif self.isEis:
         files = []
         for docElt in self.eisDocument.iter(tag="{http://www.sec.gov/edgar/common}document"):
             outfn = docElt.findtext("{http://www.sec.gov/edgar/common}conformedName")
             if outfn:
                 files.append(outfn);
         self.filesDir = files
     elif self.isXfd:
         files = []
         for data in self.xfdDocument.iter(tag="data"):
             outfn = data.findtext("filename")
             if outfn:
                 if len(outfn) > 2 and outfn[0].isalpha() and \
                     outfn[1] == ':' and outfn[2] == '\\':
                     continue
                 files.append(outfn);
         self.filesDir = files
     elif self.isRss:
         files = []  # return title, descr, pubdate, linst doc
         edgr = "http://www.sec.gov/Archives/edgar"
         try:
             for dsElt in XmlUtil.descendants(self.rssDocument, None, "item"):
                 instDoc = None
                 for instDocElt in XmlUtil.descendants(dsElt, edgr, "xbrlFile"):
                     if instDocElt.get("(http://www.sec.gov/Archives/edgar}description").endswith("INSTANCE DOCUMENT"):
                         instDoc = instDocElt.get("(http://www.sec.gov/Archives/edgar}url")
                         break
                 if not instDoc:
                     continue
                 files.append((
                     XmlUtil.text(XmlUtil.descendant(dsElt, None, "title")),
                     # tooltip
                     "{0}\n {1}\n {2}\n {3}\n {4}".format(
                         XmlUtil.text(XmlUtil.descendant(dsElt, edgr, "companyName")),
                         XmlUtil.text(XmlUtil.descendant(dsElt, edgr, "formType")),
                         XmlUtil.text(XmlUtil.descendant(dsElt, edgr, "filingDate")),
                         XmlUtil.text(XmlUtil.descendant(dsElt, edgr, "cikNumber")),
                         XmlUtil.text(XmlUtil.descendant(dsElt, edgr, "period"))),
                     XmlUtil.text(XmlUtil.descendant(dsElt, None, "description")),
                     XmlUtil.text(XmlUtil.descendant(dsElt, None, "pubDate")),
                     instDoc))
             self.filesDir = files
         except (EnvironmentError,
                 etree.LxmlError) as err:
             pass
     elif self.isInstalledTaxonomyPackage:
         files = []
         baseurlPathLen = len(os.path.dirname(self.baseurl)) + 1
         def packageDirsFiles(dir):
             for file in os.listdir(dir):
                 path = dir + "/" + file   # must have / and not \\ even on windows
                 files.append(path[baseurlPathLen:])
                 if os.path.isdir(path): 
                     packageDirsFiles(path)
         packageDirsFiles(self.baseurl[0:baseurlPathLen - 1])
         self.filesDir = files
         
     return self.filesDir
Example #42
0
 def resultIsXbrlInstance(self):
     return XmlUtil.descendant(XmlUtil.descendant(self, None, "result"), None, "instance") is not None
Example #43
0
def checkDTS(val, modelDocument, visited):
    global targetNamespaceDatePattern, efmFilenamePattern, roleTypePattern, arcroleTypePattern, \
            arcroleDefinitionPattern, namePattern, linkroleDefinitionBalanceIncomeSheet, \
            namespacesConflictPattern
    if targetNamespaceDatePattern is None:
        targetNamespaceDatePattern = re.compile(r"/([12][0-9]{3})-([01][0-9])-([0-3][0-9])|"
                                            r"/([12][0-9]{3})([01][0-9])([0-3][0-9])|")
        efmFilenamePattern = re.compile(r"^[a-z0-9][a-zA-Z0-9_\.\-]*(\.xsd|\.xml)$")
        roleTypePattern = re.compile(r"^.*/role/[^/\s]+$")
        arcroleTypePattern = re.compile(r"^.*/arcrole/[^/\s]+$")
        arcroleDefinitionPattern = re.compile(r"^.*[^\\s]+.*$")  # at least one non-whitespace character
        namePattern = re.compile("[][()*+?\\\\/^{}|@#%^=~`\"';:,<>&$\u00a3\u20ac]") # u20ac=Euro, u00a3=pound sterling 
        linkroleDefinitionBalanceIncomeSheet = re.compile(r"[^-]+-\s+Statement\s+-\s+.*(income|balance|financial\W+position)",
                                                          re.IGNORECASE)
        namespacesConflictPattern = re.compile(r"http://(xbrl\.us|fasb\.org|xbrl\.sec\.gov)/(dei|us-types|us-roles|rr)/([0-9]{4}-[0-9]{2}-[0-9]{2})$")
    nonDomainItemNameProblemPattern = re.compile(
        r"({0})|(FirstQuarter|SecondQuarter|ThirdQuarter|FourthQuarter|[1-4]Qtr|Qtr[1-4]|ytd|YTD|HalfYear)(?:$|[A-Z\W])"
        .format(re.sub(r"\W", "", (val.entityRegistrantName or "").title())))
    
        
    visited.append(modelDocument)
    definesLabelLinkbase = False
    for referencedDocument, modelDocumentReference in modelDocument.referencesDocument.items():
        #6.07.01 no includes
        if modelDocumentReference.referenceType == "include":
            val.modelXbrl.error(("EFM.6.07.01", "GFM.1.03.01", "SBR.NL.2.2.0.18"),
                _("Taxonomy schema %(schema)s includes %(include)s, only import is allowed"),
                modelObject=modelDocumentReference.referringModelObject,
                    schema=os.path.basename(modelDocument.uri), 
                    include=os.path.basename(referencedDocument.uri))
        if referencedDocument not in visited:
            checkDTS(val, referencedDocument, visited)
            
    if val.disclosureSystem.standardTaxonomiesDict is None:
        pass

    if val.validateEFM: 
        if modelDocument.uri in val.disclosureSystem.standardTaxonomiesDict:
            if modelDocument.targetNamespace:
                # check for duplicates of us-types, dei, and rr taxonomies
                match = namespacesConflictPattern.match(modelDocument.targetNamespace)
                if match is not None:
                    val.standardNamespaceConflicts[match.group(2)].add(modelDocument)
        else:
            if len(modelDocument.basename) > 32:
                val.modelXbrl.error("EFM.5.01.01.tooManyCharacters",
                    _("Document file name %(filename)s must not exceed 32 characters."),
                    modelObject=modelDocument, filename=modelDocument.basename)
            if not efmFilenamePattern.match(modelDocument.basename):
                val.modelXbrl.error("EFM.5.01.01",
                    _("Document file name %(filename)s must start with a-z or 0-9, contain upper or lower case letters, ., -, _, and end with .xsd or .xml."),
                    modelObject=modelDocument, filename=modelDocument.basename)
    
    if (modelDocument.type == ModelDocument.Type.SCHEMA and 
        modelDocument.targetNamespace not in val.disclosureSystem.baseTaxonomyNamespaces and
        modelDocument.uri.startswith(val.modelXbrl.uriDir)):
        
        # check schema contents types
        if val.validateSBRNL:
            definesLinkroles = False
            definesArcroles = False
            definesLinkParts = False
            definesAbstractItems = False
            definesNonabstractItems = False
            definesConcepts = False
            definesTuples = False
            definesPresentationTuples = False
            definesSpecificationTuples = False
            definesTypes = False
            definesEnumerations = False
            definesDimensions = False
            definesDomains = False
            definesHypercubes = False
                
        # 6.7.3 check namespace for standard authority
        targetNamespaceAuthority = UrlUtil.authority(modelDocument.targetNamespace) 
        if targetNamespaceAuthority in val.disclosureSystem.standardAuthorities:
            val.modelXbrl.error(("EFM.6.07.03", "GFM.1.03.03"),
                _("Taxonomy schema %(schema)s namespace %(targetNamespace)s is a disallowed authority"),
                modelObject=modelDocument, schema=os.path.basename(modelDocument.uri), targetNamespace=modelDocument.targetNamespace, 
                targetNamespaceAuthority=UrlUtil.authority(modelDocument.targetNamespace, includeScheme=False))
            
        # 6.7.4 check namespace format
        if modelDocument.targetNamespace is None or not modelDocument.targetNamespace.startswith("http://"):
            match = None
        elif val.validateEFMorGFM:
            targetNamespaceDate = modelDocument.targetNamespace[len(targetNamespaceAuthority):]
            match = targetNamespaceDatePattern.match(targetNamespaceDate)
        else:
            match = None
        if match is not None:
            try:
                if match.lastindex == 3:
                    date = datetime.date(int(match.group(1)),int(match.group(2)),int(match.group(3)))
                elif match.lastindex == 6:
                    date = datetime.date(int(match.group(4)),int(match.group(5)),int(match.group(6)))
                else:
                    match = None
            except ValueError:
                match = None
        if match is None:
            val.modelXbrl.error(("EFM.6.07.04", "GFM.1.03.04"),
                _("Taxonomy schema %(schema)s namespace %(targetNamespace)s must have format http://{authority}/{versionDate}"),
                modelObject=modelDocument, schema=os.path.basename(modelDocument.uri), targetNamespace=modelDocument.targetNamespace)
        elif val.fileNameDate and date > val.fileNameDate:
            val.modelXbrl.info(("EFM.6.07.06", "GFM.1.03.06"),
                _("Warning: Taxonomy schema %(schema)s namespace %(targetNamespace)s has date later than document name date %(docNameDate)s"),
                modelObject=modelDocument, schema=os.path.basename(modelDocument.uri), targetNamespace=modelDocument.targetNamespace,
                docNameDate=val.fileNameDate)

        if modelDocument.targetNamespace is not None:
            # 6.7.5 check prefix for _
            authority = UrlUtil.authority(modelDocument.targetNamespace)
            if not re.match(r"(http://|https://|ftp://|urn:)\w+",authority):
                val.modelXbrl.error(("EFM.6.07.05", "GFM.1.03.05"),
                    _("Taxonomy schema %(schema)s namespace %(targetNamespace)s must be a valid URL with a valid authority for the namespace."),
                    modelObject=modelDocument, schema=os.path.basename(modelDocument.uri), targetNamespace=modelDocument.targetNamespace)
            prefix = XmlUtil.xmlnsprefix(modelDocument.xmlRootElement,modelDocument.targetNamespace)
            if not prefix:
                val.modelXbrl.error(("EFM.6.07.07", "GFM.1.03.07"),
                    _("Taxonomy schema %(schema)s namespace %(targetNamespace)s missing prefix for the namespace."),
                    modelObject=modelDocument, schema=os.path.basename(modelDocument.uri), targetNamespace=modelDocument.targetNamespace)
            elif "_" in prefix:
                val.modelXbrl.error(("EFM.6.07.07", "GFM.1.03.07"),
                    _("Taxonomy schema %(schema)s namespace %(targetNamespace)s prefix %(prefix)s must not have an '_'"),
                    modelObject=modelDocument, schema=os.path.basename(modelDocument.uri), targetNamespace=modelDocument.targetNamespace, prefix=prefix)

            if val.validateSBRNL:
                genrlSpeclRelSet = val.modelXbrl.relationshipSet(XbrlConst.generalSpecial)
            for modelConcept in modelDocument.xmlRootElement.iterdescendants(tag="{http://www.w3.org/2001/XMLSchema}element"):
                if isinstance(modelConcept,ModelConcept):
                    # 6.7.16 name not duplicated in standard taxonomies
                    name = modelConcept.get("name")
                    if name is None: 
                        name = ""
                        if modelConcept.get("ref") is not None:
                            continue    # don't validate ref's here
                    for c in val.modelXbrl.nameConcepts.get(name, []):
                        if c.modelDocument != modelDocument:
                            if (val.validateEFMorGFM and
                                  not c.modelDocument.uri.startswith(val.modelXbrl.uriDir)):
                                val.modelXbrl.error(("EFM.6.07.16", "GFM.1.03.18"),
                                    _("Concept %(concept)s is also defined in standard taxonomy schema schema %(standardSchema)s"),
                                    modelObject=(modelConcept,c), concept=modelConcept.qname, standardSchema=os.path.basename(c.modelDocument.uri), standardConcept=c.qname)
                            elif val.validateSBRNL:
                                if not (genrlSpeclRelSet.isRelated(modelConcept, "child", c) or genrlSpeclRelSet.isRelated(c, "child", modelConcept)):
                                    val.modelXbrl.error("SBR.NL.2.2.2.02",
                                        _("Concept %(concept)s is also defined in standard taxonomy schema %(standardSchema)s without a general-special relationship"),
                                        modelObject=c, concept=modelConcept.qname, standardSchema=os.path.basename(c.modelDocument.uri))
                    ''' removed RH 2011-12-23 corresponding set up of table in ValidateFiling
                    if val.validateSBRNL and name in val.nameWordsTable:
                        if not any( any( genrlSpeclRelSet.isRelated(c, "child", modelConcept)
                                         for c in val.modelXbrl.nameConcepts.get(partialWordName, []))
                                    for partialWordName in val.nameWordsTable[name]):
                            val.modelXbrl.error("SBR.NL.2.3.2.01",
                                _("Concept %(specialName)s is appears to be missing a general-special relationship to %(generalNames)s"),
                                modelObject=c, specialName=modelConcept.qname, generalNames=', or to '.join(val.nameWordsTable[name]))
                    '''

                    # 6.7.17 id properly formed
                    id = modelConcept.id
                    requiredId = (prefix if prefix is not None else "") + "_" + name
                    if val.validateEFMorGFM and id != requiredId:
                        val.modelXbrl.error(("EFM.6.07.17", "GFM.1.03.19"),
                            _("Concept %(concept)s id %(id)s should be $(requiredId)s"),
                            modelObject=modelConcept, concept=modelConcept.qname, id=id, requiredId=requiredId)
                        
                    # 6.7.18 nillable is true
                    nillable = modelConcept.get("nillable")
                    if nillable != "true":
                        val.modelXbrl.error(("EFM.6.07.18", "GFM.1.03.20"),
                            _("Taxonomy schema %(schema)s element %(concept)s nillable %(nillable)s should be 'true'"),
                            modelObject=modelConcept, schema=os.path.basename(modelDocument.uri),
                            concept=name, nillable=nillable)
        
                    # 6.7.19 not tuple
                    if modelConcept.isTuple:
                        if val.validateEFMorGFM:
                            val.modelXbrl.error(("EFM.6.07.19", "GFM.1.03.21"),
                                _("Concept %(concept)s is a tuple"),
                                modelObject=modelConcept, concept=modelConcept.qname)
                        
                    # 6.7.20 no typed domain ref
                    if modelConcept.isTypedDimension:
                        val.modelXbrl.error(("EFM.6.07.20", "GFM.1.03.22"),
                            _("Concept %(concept)s has typedDomainRef %(typedDomainRef)s"),
                            modelObject=modelConcept, concept=modelConcept.qname,
                            typedDomainRef=modelConcept.typedDomainElement.qname if modelConcept.typedDomainElement is not None else modelConcept.typedDomainRef)
                        
                    # 6.7.21 abstract must be duration
                    isDuration = modelConcept.periodType == "duration"
                    if modelConcept.abstract == "true" and not isDuration:
                        val.modelXbrl.error(("EFM.6.07.21", "GFM.1.03.23"),
                            _("Taxonomy schema %(schema)s element %(concept)s is abstract but period type is not duration"),
                            modelObject=modelConcept, schema=os.path.basename(modelDocument.uri), concept=modelConcept.qname)
                        
                    # 6.7.22 abstract must be stringItemType
                    ''' removed SEC EFM v.17, Edgar release 10.4, and GFM 2011-04-08
                    if modelConcept.abstract == "true" and modelConcept.typeQname != XbrlConst. qnXbrliStringItemType:
                        val.modelXbrl.error(("EFM.6.07.22", "GFM.1.03.24"),
                            _("Concept %(concept)s  is abstract but type is not xbrli:stringItemType"),
                            modelObject=modelConcept, concept=modelConcept.qname)
					'''
                    substititutionGroupQname = modelConcept.substitutionGroupQname
                    # 6.7.23 Axis must be subs group dimension
                    if name.endswith("Axis") ^ (substititutionGroupQname == XbrlConst.qnXbrldtDimensionItem):
                        val.modelXbrl.error(("EFM.6.07.23", "GFM.1.03.25"),
                            _("Concept %(concept)s must end in Axis to be in xbrldt:dimensionItem substitution group"),
                            modelObject=modelConcept, concept=modelConcept.qname)

                    # 6.7.24 Table must be subs group hypercube
                    if name.endswith("Table") ^ (substititutionGroupQname == XbrlConst.qnXbrldtHypercubeItem):
                        val.modelXbrl.error(("EFM.6.07.24", "GFM.1.03.26"),
                            _("Concept %(concept)s must end in Table to be in xbrldt:hypercubeItem substitution group"),
                            modelObject=modelConcept, schema=os.path.basename(modelDocument.uri), concept=modelConcept.qname)

                    # 6.7.25 if neither hypercube or dimension, substitution group must be item
                    if substititutionGroupQname not in (None,
                                                        XbrlConst.qnXbrldtDimensionItem, 
                                                        XbrlConst.qnXbrldtHypercubeItem,
                                                        XbrlConst.qnXbrliItem):                           
                        val.modelXbrl.error(("EFM.6.07.25", "GFM.1.03.27"),
                            _("Concept %(concept)s has disallowed substitution group %(substitutionGroup)s"),
                            modelObject=modelConcept, concept=modelConcept.qname,
                            substitutionGroup=modelConcept.substitutionGroupQname)
                        
                    # 6.7.26 Table must be subs group hypercube
                    if name.endswith("LineItems") and modelConcept.abstract != "true":
                        val.modelXbrl.error(("EFM.6.07.26", "GFM.1.03.28"),
                            _("Concept %(concept)s is a LineItems but not abstract"),
                            modelObject=modelConcept, concept=modelConcept.qname)

                    # 6.7.27 type domainMember must end with Domain or Member
                    conceptType = modelConcept.type
                    isDomainItemType = conceptType is not None and conceptType.isDomainItemType
                    endsWithDomainOrMember = name.endswith("Domain") or name.endswith("Member")
                    if isDomainItemType != endsWithDomainOrMember:
                        val.modelXbrl.error(("EFM.6.07.27", "GFM.1.03.29"),
                            _("Concept %(concept)s must end with Domain or Member for type of domainItemType"),
                            modelObject=modelConcept, concept=modelConcept.qname)

                    # 6.7.28 domainItemType must be duration
                    if isDomainItemType and not isDuration:
                        val.modelXbrl.error(("EFM.6.07.28", "GFM.1.03.30"),
                            _("Concept %(concept)s is a domainItemType and must be periodType duration"),
                            modelObject=modelConcept, concept=modelConcept.qname)
                        
                    # 6.8.5 semantic check, check LC3 name
                    if not name[0].isupper():
                        val.modelXbrl.log("ERROR-SEMANTIC", ("EFM.6.08.05.firstLetter", "GFM.2.03.05.firstLetter"),
                            _("Concept %(concept)s name must start with a capital letter"),
                            modelObject=modelConcept, concept=modelConcept.qname)
                    if namePattern.search(name):
                        val.modelXbrl.log("ERROR-SEMANTIC", ("EFM.6.08.05.disallowedCharacter", "GFM.2.03.05.disallowedCharacter"),
                            _("Concept %(concept)s has disallowed name character"),
                            modelObject=modelConcept, concept=modelConcept.qname)
                    if len(name) > 200:
                        val.modelXbrl.log("ERROR-SEMANTIC", "EFM.6.08.05.nameLength",
                            _("Concept %(concept)s name length %(namelength)s exceeds 200 characters"),
                            modelObject=modelConcept, concept=modelConcept.qname, namelength=len(name))
                        
                    if val.validateEFM:
                        label = modelConcept.label(lang="en-US", fallbackToQname=False)
                        if label:
                            # allow Joe's Bar, N.A.  to be JoesBarNA -- remove ', allow A. as not article "a"
                            lc3name = ''.join(re.sub(r"['.-]", "", (w[0] or w[2] or w[3] or w[4])).title()
                                              for w in re.findall(r"((\w+')+\w+)|(A[.-])|([.-]A(?=\W|$))|(\w+)", label) # EFM implies this should allow - and . re.findall(r"[\w\-\.]+", label)
                                              if w[4].lower() not in ("the", "a", "an"))
                            if not(name == lc3name or 
                                   (name and lc3name and lc3name[0].isdigit() and name[1:] == lc3name and (name[0].isalpha() or name[0] == '_'))):
                                val.modelXbrl.log("WARNING-SEMANTIC", "EFM.6.08.05.LC3",
                                    _("Concept %(concept)s should match expected LC3 composition %(lc3name)s"),
                                    modelObject=modelConcept, concept=modelConcept.qname, lc3name=lc3name)
                                
                    if conceptType is not None:
                        # 6.8.6 semantic check
                        if not isDomainItemType and conceptType.qname != XbrlConst.qnXbrliDurationItemType:
                            nameProblems = nonDomainItemNameProblemPattern.findall(name)
                            if any(any(t) for t in nameProblems):  # list of tuples with possibly nonempty strings
                                val.modelXbrl.log("WARNING-SEMANTIC", ("EFM.6.08.06", "GFM.2.03.06"),
                                    _("Concept %(concept)s should not contain company or period information, found: %(matches)s"),
                                    modelObject=modelConcept, concept=modelConcept.qname, 
                                    matches=", ".join(''.join(t) for t in nameProblems))
                        
                        if conceptType.qname == XbrlConst.qnXbrliMonetaryItemType:
                            if not modelConcept.balance:
                                # 6.8.11 may not appear on a income or balance statement
                                if any(linkroleDefinitionBalanceIncomeSheet.match(roleType.definition)
                                       for rel in val.modelXbrl.relationshipSet(XbrlConst.parentChild).toModelObject(modelConcept)
                                       for roleType in val.modelXbrl.roleTypes.get(rel.linkrole,())):
                                    val.modelXbrl.log("ERROR-SEMANTIC", ("EFM.6.08.11", "GFM.2.03.11"),
                                        _("Concept %(concept)s must have a balance because it appears in a statement of income or balance sheet"),
                                        modelObject=modelConcept, concept=modelConcept.qname)
                                # 6.11.5 semantic check, must have a documentation label
                                stdLabel = modelConcept.label(lang="en-US", fallbackToQname=False)
                                defLabel = modelConcept.label(preferredLabel=XbrlConst.documentationLabel, lang="en-US", fallbackToQname=False)
                                if not defLabel or ( # want different words than std label
                                    stdLabel and re.findall(r"\w+", stdLabel) == re.findall(r"\w+", defLabel)):
                                    val.modelXbrl.log("ERROR-SEMANTIC", ("EFM.6.11.05", "GFM.2.04.04"),
                                        _("Concept %(concept)s is monetary without a balance and must have a documentation label that disambiguates its sign"),
                                        modelObject=modelConcept, concept=modelConcept.qname)
                        
                        # 6.8.16 semantic check
                        if conceptType.qname == XbrlConst.qnXbrliDateItemType and modelConcept.periodType != "duration":
                            val.modelXbrl.log("ERROR-SEMANTIC", ("EFM.6.08.16", "GFM.2.03.16"),
                                _("Concept %(concept)s of type xbrli:dateItemType must have periodType duration"),
                                modelObject=modelConcept, concept=modelConcept.qname)
                        
                        # 6.8.17 semantic check
                        if conceptType.qname == XbrlConst.qnXbrliStringItemType and modelConcept.periodType != "duration":
                            val.modelXbrl.log("ERROR-SEMANTIC", ("EFM.6.08.17", "GFM.2.03.17"),
                                _("Concept %(concept)s of type xbrli:stringItemType must have periodType duration"),
                                modelObject=modelConcept, concept=modelConcept.qname)
                        
                    if val.validateSBRNL:
                        if modelConcept.isTuple:
                            if modelConcept.substitutionGroupQname.localName == "presentationTuple" and modelConcept.substitutionGroupQname.namespaceURI.endswith("/basis/sbr/xbrl/xbrl-syntax-extension"): # namespace may change each year
                                definesPresentationTuples = True
                            elif modelConcept.substitutionGroupQname.localName == "specificationTuple" and modelConcept.substitutionGroupQname.namespaceURI.endswith("/basis/sbr/xbrl/xbrl-syntax-extension"): # namespace may change each year
                                definesSpecificationTuples = True
                            else:
                                definesTuples = True
                            definesConcepts = True
                            if modelConcept.isAbstract:
                                val.modelXbrl.error("SBR.NL.2.2.2.03",
                                    _("Concept %(concept)s is an abstract tuple"),
                                    modelObject=modelConcept, concept=modelConcept.qname)
                            if tupleCycle(val,modelConcept):
                                val.modelXbrl.error("SBR.NL.2.2.2.07",
                                    _("Tuple %(concept)s has a tuple cycle"),
                                    modelObject=modelConcept, concept=modelConcept.qname)
                            if modelConcept.get("nillable") != "false" and modelConcept.isRoot:
                                val.modelXbrl.error("SBR.NL.2.2.2.17", #don't want default, just what was really there
                                    _("Tuple %(concept)s must have nillable='false'"),
                                    modelObject=modelConcept, concept=modelConcept.qname)
                        elif modelConcept.isItem:
                            definesConcepts = True
                        if modelConcept.abstract == "true":
                            if modelConcept.isRoot:
                                if modelConcept.get("nillable") != "false": #don't want default, just what was really there
                                    val.modelXbrl.error("SBR.NL.2.2.2.16",
                                        _("Abstract root concept %(concept)s must have nillable='false'"),
                                    modelObject=modelConcept, concept=modelConcept.qname)
                                if modelConcept.typeQname != XbrlConst.qnXbrliStringItemType:
                                    val.modelXbrl.error("SBR.NL.2.2.2.21",
                                        _("Abstract root concept %(concept)s must have type='xbrli:stringItemType'"),
                                    modelObject=modelConcept, concept=modelConcept.qname)
                            if modelConcept.balance:
                                val.modelXbrl.error("SBR.NL.2.2.2.22",
                                    _("Abstract concept %(concept)s must not have a balance attribute"),
                                    modelObject=modelConcept, concept=modelConcept.qname)
                            if modelConcept.isHypercubeItem:
                                definesHypercubes = True
                            elif modelConcept.isDimensionItem:
                                definesDimensions = True
                            elif substititutionGroupQname and substititutionGroupQname.localName in ("domainItem","domainMemberItem"):
                                definesDomains = True
                            elif modelConcept.isItem:
                                definesAbstractItems = True
                        else:   # not abstract
                            if modelConcept.isItem:
                                definesNonabstractItems = True
                                if not (modelConcept.label(preferredLabel=XbrlConst.documentationLabel,fallbackToQname=False,lang="nl") or
                                        val.modelXbrl.relationshipSet(XbrlConst.conceptReference).fromModelObject(c) or
                                        modelConcept.genLabel(role=XbrlConst.genDocumentationLabel,lang="nl") or
                                        val.modelXbrl.relationshipSet(XbrlConst.elementReference).fromModelObject(c)):
                                    val.modelXbrl.error("SBR.NL.2.2.2.28",
                                        _("Concept %(concept)s must have a documentation label or reference"),
                                        modelObject=modelConcept, concept=modelConcept.qname)
                        if modelConcept.balance and not modelConcept.instanceOfType(XbrlConst.qnXbrliMonetaryItemType):
                            val.modelXbrl.error("SBR.NL.2.2.2.24",
                                _("Non-monetary concept %(concept)s must not have a balance attribute"),
                                modelObject=modelConcept, concept=modelConcept.qname)
                        if modelConcept.isLinkPart:
                            definesLinkParts = True
                            val.modelXbrl.error("SBR.NL.2.2.5.01",
                                _("Link:part concept %(concept)s is not allowed"),
                                modelObject=modelConcept, concept=modelConcept.qname)
                            if not modelConcept.genLabel(fallbackToQname=False,lang="nl"):
                                val.modelXbrl.error("SBR.NL.2.2.5.02",
                                    _("Link part definition %(concept)s must have a generic label in language 'nl'"),
                                    modelObject=modelConcept, concept=modelConcept.qname)
        # 6.7.8 check for embedded linkbase
        for e in modelDocument.xmlRootElement.iterdescendants(tag="{http://www.xbrl.org/2003/linkbase}linkbase"):
            if isinstance(e,ModelObject):
                val.modelXbrl.error(("EFM.6.07.08", "GFM.1.03.08"),
                    _("Taxonomy schema %(schema)s contains an embedded linkbase"),
                    modelObject=e, schema=modelDocument.basename)
                break

        requiredUsedOns = {XbrlConst.qnLinkPresentationLink,
                           XbrlConst.qnLinkCalculationLink,
                           XbrlConst.qnLinkDefinitionLink}
        
        standardUsedOns = {XbrlConst.qnLinkLabel, XbrlConst.qnLinkReference, 
                           XbrlConst.qnLinkDefinitionArc, XbrlConst.qnLinkCalculationArc, XbrlConst.qnLinkPresentationArc, 
                           XbrlConst.qnLinkLabelArc, XbrlConst.qnLinkReferenceArc, 
                           # per WH, private footnote arc and footnore resource roles are not allowed
                           XbrlConst.qnLinkFootnoteArc, XbrlConst.qnLinkFootnote,
                           }

        # 6.7.9 role types authority
        for e in modelDocument.xmlRootElement.iterdescendants(tag="{http://www.xbrl.org/2003/linkbase}roleType"):
            if isinstance(e,ModelObject):
                roleURI = e.get("roleURI")
                if targetNamespaceAuthority != UrlUtil.authority(roleURI):
                    val.modelXbrl.error(("EFM.6.07.09", "GFM.1.03.09"),
                        _("RoleType %(roleType)s does not match authority %(targetNamespaceAuthority)s"),
                        modelObject=e, roleType=roleURI, targetNamespaceAuthority=targetNamespaceAuthority, targetNamespace=modelDocument.targetNamespace)
                # 6.7.9 end with .../role/lc3 name
                if not roleTypePattern.match(roleURI):
                    val.modelXbrl.warning(("EFM.6.07.09.roleEnding", "GFM.1.03.09"),
                        "RoleType %(roleType)s should end with /role/{LC3name}",
                        modelObject=e, roleType=roleURI)
                    
                # 6.7.10 only one role type declaration in DTS
                modelRoleTypes = val.modelXbrl.roleTypes.get(roleURI)
                if modelRoleTypes is not None:
                    modelRoleType = modelRoleTypes[0]
                    definition = modelRoleType.definitionNotStripped
                    usedOns = modelRoleType.usedOns
                    if len(modelRoleTypes) == 1:
                        # 6.7.11 used on's for pre, cal, def if any has a used on
                        if not usedOns.isdisjoint(requiredUsedOns) and len(requiredUsedOns - usedOns) > 0:
                            val.modelXbrl.error(("EFM.6.07.11", "GFM.1.03.11"),
                                _("RoleType %(roleType)s missing used on %(usedOn)s"),
                                modelObject=e, roleType=roleURI, usedOn=requiredUsedOns - usedOns)
                            
                        # 6.7.12 definition match pattern
                        if (val.disclosureSystem.roleDefinitionPattern is not None and
                            (definition is None or not val.disclosureSystem.roleDefinitionPattern.match(definition))):
                            val.modelXbrl.error(("EFM.6.07.12", "GFM.1.03.12-14"),
                                _("RoleType %(roleType)s definition \"%(definition)s\" must match {Sortcode} - {Type} - {Title}"),
                                modelObject=e, roleType=roleURI, definition=(definition or ""))

                    if usedOns & standardUsedOns: # semantics check
                        val.modelXbrl.log("ERROR-SEMANTIC", ("EFM.6.08.03", "GFM.2.03.03"),
                            _("RoleType %(roleuri)s is defined using role types already defined by standard roles for: %(qnames)s"),
                            modelObject=e, roleuri=roleURI, qnames=', '.join(str(qn) for qn in usedOns & standardUsedOns))

                    if val.validateSBRNL:
                        if usedOns & XbrlConst.standardExtLinkQnames or XbrlConst.qnGenLink in usedOns:
                            definesLinkroles = True
                            if not e.genLabel():
                                val.modelXbrl.error("SBR.NL.2.2.3.03",
                                    _("Link RoleType %(roleType)s missing a generic standard label"),
                                    modelObject=e, roleType=roleURI)
                            nlLabel = e.genLabel(lang="nl")
                            if definition != nlLabel:
                                val.modelXbrl.error("SBR.NL.2.2.3.04",
                                    _("Link RoleType %(roleType)s definition does not match NL standard generic label, \ndefinition: %(definition)s \nNL label: %(label)s"),
                                    modelObject=e, roleType=roleURI, definition=definition, label=nlLabel)
                        if definition and (definition[0].isspace() or definition[-1].isspace()):
                            val.modelXbrl.error("SBR.NL.2.2.3.07",
                                _('Link RoleType %(roleType)s definition has leading or trailing spaces: "%(definition)s"'),
                                modelObject=e, roleType=roleURI, definition=definition)

        # 6.7.13 arcrole types authority
        for e in modelDocument.xmlRootElement.iterdescendants(tag="{http://www.xbrl.org/2003/linkbase}arcroleType"):
            if isinstance(e,ModelObject):
                arcroleURI = e.get("arcroleURI")
                if targetNamespaceAuthority != UrlUtil.authority(arcroleURI):
                    val.modelXbrl.error(("EFM.6.07.13", "GFM.1.03.15"),
                        _("ArcroleType %(arcroleType)s does not match authority %(targetNamespaceAuthority)s"),
                        modelObject=e, arcroleType=arcroleURI, targetNamespaceAuthority=targetNamespaceAuthority, targetNamespace=modelDocument.targetNamespace)
                # 6.7.13 end with .../arcrole/lc3 name
                if not arcroleTypePattern.match(arcroleURI):
                    val.modelXbrl.warning(("EFM.6.07.13.arcroleEnding", "GFM.1.03.15"),
                        _("ArcroleType %(arcroleType)s should end with /arcrole/{LC3name}"),
                        modelObject=e, arcroleType=arcroleURI)
                    
                # 6.7.15 definition match pattern
                modelRoleTypes = val.modelXbrl.arcroleTypes[arcroleURI]
                definition = modelRoleTypes[0].definition
                if definition is None or not arcroleDefinitionPattern.match(definition):
                    val.modelXbrl.error(("EFM.6.07.15", "GFM.1.03.17"),
                        _("ArcroleType %(arcroleType)s definition must be non-empty"),
                        modelObject=e, arcroleType=arcroleURI)
    
                # semantic checks
                usedOns = modelRoleTypes[0].usedOns
                if usedOns & standardUsedOns: # semantics check
                    val.modelXbrl.log("ERROR-SEMANTIC", ("EFM.6.08.03", "GFM.2.03.03"),
                        _("ArcroleType %(arcroleuri)s is defined using role types already defined by standard arcroles for: %(qnames)s"),
                        modelObject=e, arcroleuri=arcroleURI, qnames=', '.join(str(qn) for qn in usedOns & standardUsedOns))

                if val.validateSBRNL:
                    definesArcroles = True
                    val.modelXbrl.error("SBR.NL.2.2.4.01",
                        _("Arcrole type definition is not allowed: %(arcroleURI)s"),
                        modelObject=e, arcroleURI=arcroleURI)
                    
        if val.validateSBRNL:
            for appinfoElt in modelDocument.xmlRootElement.iter(tag="{http://www.w3.org/2001/XMLSchema}appinfo"):
                for nonLinkElt in appinfoElt.iterdescendants():
                    if isinstance(nonLinkElt, ModelObject) and nonLinkElt.namespaceURI != XbrlConst.link:
                        val.modelXbrl.error("SBR.NL.2.2.11.05",
                            _("Appinfo contains disallowed non-link element %(element)s"),
                            modelObject=nonLinkElt, element=nonLinkElt.qname)

            for cplxTypeElt in modelDocument.xmlRootElement.iter(tag="{http://www.w3.org/2001/XMLSchema}complexType"):
                choiceElt = cplxTypeElt.find("{http://www.w3.org/2001/XMLSchema}choice")
                if choiceElt is not None:
                    val.modelXbrl.error("SBR.NL.2.2.11.09",
                        _("ComplexType contains disallowed xs:choice element"),
                        modelObject=choiceElt)
                    
            for cplxContentElt in modelDocument.xmlRootElement.iter(tag="{http://www.w3.org/2001/XMLSchema}complexContent"):
                if XmlUtil.descendantAttr(cplxContentElt, "http://www.w3.org/2001/XMLSchema", ("extension","restriction"), "base") != "sbr:placeholder":
                    val.modelXbrl.error("SBR.NL.2.2.11.10",
                        _("ComplexContent is disallowed"),
                        modelObject=cplxContentElt)

            definesTypes = (modelDocument.xmlRootElement.find("{http://www.w3.org/2001/XMLSchema}complexType") is not None or
                            modelDocument.xmlRootElement.find("{http://www.w3.org/2001/XMLSchema}simpleType") is not None)
            
            for enumElt in modelDocument.xmlRootElement.iter(tag="{http://www.w3.org/2001/XMLSchema}enumeration"):
                definesEnumerations = True
                if any(not valueElt.genLabel(lang="nl")
                       for valueElt in enumElt.iter(tag="{http://www.w3.org/2001/XMLSchema}value")):
                    val.modelXbrl.error("SBR.NL.2.2.7.05",
                        _("Enumeration element has value(s) without generic label."),
                        modelObject=enumElt)

            if (definesLinkroles + definesArcroles + definesLinkParts +
                definesAbstractItems + definesNonabstractItems + 
                definesTuples + definesPresentationTuples + definesSpecificationTuples + definesTypes +
                definesEnumerations + definesDimensions + definesDomains + 
                definesHypercubes) != 1:
                schemaContents = []
                if definesLinkroles: schemaContents.append(_("linkroles"))
                if definesArcroles: schemaContents.append(_("arcroles"))
                if definesLinkParts: schemaContents.append(_("link parts"))
                if definesAbstractItems: schemaContents.append(_("abstract items"))
                if definesNonabstractItems: schemaContents.append(_("nonabstract items"))
                if definesTuples: schemaContents.append(_("tuples"))
                if definesPresentationTuples: schemaContents.append(_("sbrPresentationTuples"))
                if definesSpecificationTuples: schemaContents.append(_("sbrSpecificationTuples"))
                if definesTypes: schemaContents.append(_("types"))
                if definesEnumerations: schemaContents.append(_("enumerations"))
                if definesDimensions: schemaContents.append(_("dimensions"))
                if definesDomains: schemaContents.append(_("domains"))
                if definesHypercubes: schemaContents.append(_("hypercubes"))
                if schemaContents:
                    if not ((definesTuples or definesPresentationTuples or definesSpecificationTuples) and
                            not (definesLinkroles or definesArcroles or definesLinkParts or definesAbstractItems or
                                 definesTypes or definesDimensions or definesDomains or definesHypercubes)):
                        val.modelXbrl.error("SBR.NL.2.2.1.01",
                            _("Taxonomy schema may only define one of these: %(contents)s"),
                            modelObject=modelDocument, contents=', '.join(schemaContents))
                elif not any(refDoc.inDTS and refDoc.targetNamespace not in val.disclosureSystem.baseTaxonomyNamespaces
                             for refDoc in modelDocument.referencesDocument.keys()): # no linkbase ref or includes
                    val.modelXbrl.error("SBR.NL.2.2.1.01",
                        _("Taxonomy schema must be a DTS entrypoint OR define linkroles OR arcroles OR link:parts OR context fragments OR abstract items OR tuples OR non-abstract elements OR types OR enumerations OR dimensions OR domains OR hypercubes"),
                        modelObject=modelDocument)
            if definesConcepts ^ any(  # xor so either concepts and no label LB or no concepts and has label LB
                       (refDoc.type == ModelDocument.Type.LINKBASE and
                        XmlUtil.descendant(refDoc.xmlRootElement, XbrlConst.link, "labelLink") is not None)
                       for refDoc in modelDocument.referencesDocument.keys()): # no label linkbase
                val.modelXbrl.error("SBR.NL.2.2.1.02",
                    _("A schema that defines concepts MUST have a linked 2.1 label linkbase"),
                    modelObject=modelDocument)
            if (definesNonabstractItems or definesTuples) and not any(  # was xor but changed to and not per RH 1/11/12
                       (refDoc.type == ModelDocument.Type.LINKBASE and
                       (XmlUtil.descendant(refDoc.xmlRootElement, XbrlConst.link, "referenceLink") is not None or
                        XmlUtil.descendant(refDoc.xmlRootElement, XbrlConst.link, "label", "{http://www.w3.org/1999/xlink}role", "http://www.xbrl.org/2003/role/documentation" ) is not None))
                        for refDoc in modelDocument.referencesDocument.keys()):
                val.modelXbrl.error("SBR.NL.2.2.1.03",
                    _("A schema that defines non-abstract items MUST have a linked (2.1) reference linkbase AND/OR a label linkbase with @xlink:role=documentation"),
                    modelObject=modelDocument)

        #6.3.3 filename check
        m = re.match(r"^\w+-([12][0-9]{3}[01][0-9][0-3][0-9]).xsd$", modelDocument.basename)
        if m:
            try: # check date value
                datetime.datetime.strptime(m.group(1),"%Y%m%d").date()
                # date and format are ok, check "should" part of 6.3.3
                if val.fileNameBasePart:
                    expectedFilename = "{0}-{1}.xsd".format(val.fileNameBasePart, val.fileNameDatePart)
                    if modelDocument.basename != expectedFilename:
                        val.modelXbrl.log("WARNING-SEMANTIC", ("EFM.6.03.03.matchInstance", "GFM.1.01.01.matchInstance"),
                            _('Schema file name warning: %(filename)s, should match %(expectedFilename)s'),
                            modelObject=modelDocument, filename=modelDocument.basename, expectedFilename=expectedFilename)
            except ValueError:
                val.modelXbrl.error(("EFM.6.03.03", "GFM.1.01.01"),
                    _('Invalid schema file base name part (date) in "{base}-{yyyymmdd}.xsd": %(filename)s'),
                    modelObject=modelDocument, filename=modelDocument.basename)
        else:
            val.modelXbrl.error(("EFM.6.03.03", "GFM.1.01.01"),
                _('Invalid schema file name, must match "{base}-{yyyymmdd}.xsd": %(filename)s'),
                modelObject=modelDocument, filename=modelDocument.basename)

    elif modelDocument.type == ModelDocument.Type.LINKBASE:
        # if it is part of the submission (in same directory) check name
        if modelDocument.filepath.startswith(val.modelXbrl.modelDocument.filepathdir):
            #6.3.3 filename check
            extLinkElt = XmlUtil.descendant(modelDocument.xmlRootElement, XbrlConst.link, "*", "{http://www.w3.org/1999/xlink}type", "extended")
            if extLinkElt is None:# no ext link element
                val.modelXbrl.error(("EFM.6.03.03.noLinkElement", "GFM.1.01.01.noLinkElement"),
                    _('Invalid linkbase file name: %(filename)s, has no extended link element, cannot determine link type.'),
                    modelObject=modelDocument, filename=modelDocument.basename)
            elif extLinkElt.localName not in extLinkEltFileNameEnding:
                val.modelXbrl.error("EFM.6.03.02",
                    _('Invalid linkbase link element %(linkElement)s in %(filename)s'),
                    modelObject=modelDocument, linkElement=extLinkElt.localName, filename=modelDocument.basename)
            else:
                m = re.match(r"^\w+-([12][0-9]{3}[01][0-9][0-3][0-9])(_[a-z]{3}).xml$", modelDocument.basename)
                expectedSuffix = extLinkEltFileNameEnding[extLinkElt.localName]
                if m and m.group(2) == expectedSuffix:
                    try: # check date value
                        datetime.datetime.strptime(m.group(1),"%Y%m%d").date()
                        # date and format are ok, check "should" part of 6.3.3
                        if val.fileNameBasePart:
                            expectedFilename = "{0}-{1}{2}.xml".format(val.fileNameBasePart, val.fileNameDatePart, expectedSuffix)
                            if modelDocument.basename != expectedFilename:
                                val.modelXbrl.log("WARNING-SEMANTIC", ("EFM.6.03.03.matchInstance", "GFM.1.01.01.matchInstance"),
                                    _('Linkbase name warning: %(filename)s should match %(expectedFilename)s'),
                                    modelObject=modelDocument, filename=modelDocument.basename, expectedFilename=expectedFilename)
                    except ValueError:
                        val.modelXbrl.error(("EFM.6.03.03", "GFM.1.01.01"),
                            _('Invalid linkbase base file name part (date) in "{base}-{yyyymmdd}_{suffix}.xml": %(filename)s'),
                            modelObject=modelDocument, filename=modelDocument.basename)
                else:
                    val.modelXbrl.error(("EFM.6.03.03", "GFM.1.01.01"),
                        _('Invalid linkbase name, must match "{base}-{yyyymmdd}%(expectedSuffix)s.xml": %(filename)s'),
                        modelObject=modelDocument, filename=modelDocument.basename, expectedSuffix=expectedSuffix)
    visited.remove(modelDocument)
 def description(self):
     nameElement = XmlUtil.descendant(self, None,
                                      ("description", "documentation"))
     if nameElement is not None:
         return XmlUtil.innerText(nameElement)
     return None
Example #45
0
 def assignmentRefs(self):
     return XmlUtil.childrenAttrs(self, XbrlConst.ver, "assignmentRef",
                                  "ref")
 def expectedVersioningReport(self):
     XmlUtil.text(
         XmlUtil.text(
             XmlUtil.descendant(XmlUtil.descendant(self, None, "result"),
                                None, "versioningReport")))
Example #47
0
 def toResourceValue(self):
     return XmlUtil.childAttr(self, XbrlConst.verce, "toResource", "value")
    def expected(self):
        for pluginXbrlMethod in pluginClassMethods(
                "ModelTestcaseVariation.ExpectedResult"):
            expected = pluginXbrlMethod(self)
            if expected:
                return expected
        # default behavior without plugins
        if self.localName == "testcase":
            return self.document.basename[:4]  #starts with PASS or FAIL
        elif self.localName == "testGroup":  #w3c testcase
            instanceTestElement = XmlUtil.descendant(self, None,
                                                     "instanceTest")
            if instanceTestElement is not None:  # take instance first
                return XmlUtil.descendantAttr(instanceTestElement, None,
                                              "expected", "validity")
            else:
                schemaTestElement = XmlUtil.descendant(self, None,
                                                       "schemaTest")
                if schemaTestElement is not None:
                    return XmlUtil.descendantAttr(schemaTestElement, None,
                                                  "expected", "validity")
        resultElement = XmlUtil.descendant(self, None, "result")
        if resultElement is not None:
            expected = resultElement.get("expected")
            if expected and resultElement.get(
                    "nonStandardErrorCodes") == "true":
                # if @expected and @nonStandardErrorCodes then use expected instead of error codes
                return expected
        errorElement = XmlUtil.descendant(self, None, "error")
        resultElement = XmlUtil.descendant(self, None, "result")
        if errorElement is not None and not errorElement.get(
                "nonStandardErrorCodes"):
            _errorText = XmlUtil.text(errorElement)
            if ' ' in _errorText:  # list of tokens
                return _errorText
            return ModelValue.qname(errorElement,
                                    _errorText)  # turn into a QName
        if resultElement is not None:
            if expected:
                return expected
            for assertElement in XmlUtil.children(resultElement, None,
                                                  "assert"):
                num = assertElement.get("num")
                if num == "99999":  # inline test, use name as expected
                    return assertElement.get("name")
                if len(num) == 5:
                    return "EFM.{0}.{1}.{2}".format(num[0], num[1:3], num[3:6])
            asserTests = {}
            for atElt in XmlUtil.children(resultElement, None,
                                          "assertionTests"):
                try:
                    asserTests[atElt.get("assertionID")] = (
                        _INT(atElt.get("countSatisfied")),
                        _INT(atElt.get("countNotSatisfied")))
                except ValueError:
                    pass
            if asserTests:
                return asserTests
        elif self.get("result"):
            return self.get("result")

        return None
Example #49
0
 def toConceptQname(self):
     toConcept = XmlUtil.child(self, XbrlConst.vercb, "toConcept")
     if toConcept is not None and toConcept.get("name"):
         return qname(toConcept, toConcept.get("name"))
     else:
         return None
 def resultIsTaxonomyPackage(self):
     return any(e.localName
                for e in XmlUtil.descendants(self, None, TXMY_PKG_SRC_ELTS))
Example #51
0
 def actionId(self):
     return XmlUtil.parentId(self, XbrlConst.ver, "action")
 def readMeFirstUris(self):
     try:
         return self._readMeFirstUris
     except AttributeError:
         self._readMeFirstUris = []
         # first look if any plugin method to get readme first URIs
         if not any(
                 pluginXbrlMethod(self)
                 for pluginXbrlMethod in pluginClassMethods(
                     "ModelTestcaseVariation.ReadMeFirstUris")):
             if self.localName == "testGroup":  #w3c testcase
                 instanceTestElement = XmlUtil.descendant(
                     self, None, "instanceTest")
                 if instanceTestElement is not None:  # take instance first
                     self._readMeFirstUris.append(
                         XmlUtil.descendantAttr(
                             instanceTestElement, None, "instanceDocument",
                             "{http://www.w3.org/1999/xlink}href"))
                 else:
                     schemaTestElement = XmlUtil.descendant(
                         self, None, "schemaTest")
                     if schemaTestElement is not None:
                         self._readMeFirstUris.append(
                             XmlUtil.descendantAttr(
                                 schemaTestElement, None, "schemaDocument",
                                 "{http://www.w3.org/1999/xlink}href"))
             elif self.localName == "test-case":  #xpath testcase
                 inputFileElement = XmlUtil.descendant(
                     self, None, "input-file")
                 if inputFileElement is not None:  # take instance first
                     self._readMeFirstUris.append("TestSources/" +
                                                  inputFileElement.text +
                                                  ".xml")
             elif self.resultIsTaxonomyPackage:
                 self._readMeFirstUris.append(
                     os.path.join(self.modelDocument.filepathdir, "tests",
                                  self.get("name") + ".zip"))
             else:
                 # default built-in method for readme first uris
                 for anElement in self.iterdescendants():
                     if isinstance(anElement,
                                   ModelObject) and anElement.get(
                                       "readMeFirst") == "true":
                         if anElement.get(
                                 "{http://www.w3.org/1999/xlink}href"):
                             uri = anElement.get(
                                 "{http://www.w3.org/1999/xlink}href")
                         else:
                             uri = XmlUtil.innerText(anElement)
                         if anElement.get("name"):
                             self._readMeFirstUris.append(
                                 (ModelValue.qname(anElement,
                                                   anElement.get("name")),
                                  uri))
                         elif anElement.get("dts"):
                             self._readMeFirstUris.append(
                                 (anElement.get("dts"), uri))
                         else:
                             self._readMeFirstUris.append(uri)
         if not self._readMeFirstUris:  # provide a dummy empty instance document
             self._readMeFirstUris.append(
                 os.path.join(self.modelXbrl.modelManager.cntlr.configDir,
                              "empty-instance.xml"))
         return self._readMeFirstUris
Example #53
0
 def linkbaseDiscover(self, linkbaseElement, inInstance=False):
     for lbElement in linkbaseElement.childNodes:
         if lbElement.nodeType == 1:  #element
             lbLn = lbElement.localName
             lbNs = lbElement.namespaceURI
             if lbNs == XbrlConst.link:
                 if lbLn == "roleRef" or lbLn == "arcroleRef":
                     href = self.discoverHref(lbElement)
                     if href is None:
                         self.modelXbrl.error(
                             "Linkbase in {0} {1} href attribute missing or malformed"
                             .format(os.path.basename(self.uri),
                                     lbLn), "err", "xbrl:hrefMissing")
                     else:
                         self.hrefObjects.append(href)
                     continue
             if lbElement.getAttributeNS(XbrlConst.xlink,
                                         "type") == "extended":
                 self.schemalocateElementNamespace(lbElement)
                 arcrolesFound = set()
                 dimensionArcFound = False
                 formulaArcFound = False
                 euRenderingArcFound = False
                 linkQn = qname(lbElement)
                 linkrole = lbElement.getAttributeNS(
                     XbrlConst.xlink, "role")
                 modelLink = ModelObject.createLink(self, lbElement)
                 if inInstance:
                     #index footnote links even if no arc children
                     baseSetKeys = (("XBRL-footnotes", None, None, None),
                                    ("XBRL-footnotes", linkrole, None,
                                     None))
                     for baseSetKey in baseSetKeys:
                         self.modelXbrl.baseSets[baseSetKey].append(
                             modelLink)
                 for linkElement in lbElement.childNodes:
                     if linkElement.nodeType == 1:  #element
                         self.schemalocateElementNamespace(linkElement)
                         xlinkType = linkElement.getAttributeNS(
                             XbrlConst.xlink, "type")
                         modelResource = None
                         if xlinkType == "locator":
                             nonDTS = linkElement.namespaceURI != XbrlConst.link or linkElement.localName != "loc"
                             # only link:loc elements are discovered or processed
                             href = self.discoverHref(linkElement,
                                                      nonDTS=nonDTS)
                             if href is None:
                                 self.modelXbrl.error(
                                     "Linkbase in {0} {1} href attribute missing or malformed"
                                     .format(os.path.basename(self.uri),
                                             lbLn), "err",
                                     "xbrl:hrefMissing")
                             else:
                                 modelResource = ModelObject.createLocator(
                                     self, linkElement, href)
                         elif xlinkType == "arc":
                             arcQn = qname(linkElement)
                             arcrole = linkElement.getAttributeNS(
                                 XbrlConst.xlink, "arcrole")
                             if arcrole not in arcrolesFound:
                                 if linkrole == "":
                                     linkrole = XbrlConst.defaultLinkRole
                                 #index by both arcrole and linkrole#arcrole and dimensionsions if applicable
                                 baseSetKeys = [(arcrole, linkrole, linkQn,
                                                 arcQn)]
                                 baseSetKeys.append(
                                     (arcrole, linkrole, None, None))
                                 baseSetKeys.append(
                                     (arcrole, None, None, None))
                                 if XbrlConst.isDimensionArcrole(
                                         arcrole) and not dimensionArcFound:
                                     baseSetKeys.append(("XBRL-dimensions",
                                                         None, None, None))
                                     baseSetKeys.append(
                                         ("XBRL-dimensions", linkrole, None,
                                          None))
                                     dimensionArcFound = True
                                 if XbrlConst.isFormulaArcrole(
                                         arcrole) and not formulaArcFound:
                                     baseSetKeys.append(("XBRL-formulae",
                                                         None, None, None))
                                     baseSetKeys.append(
                                         ("XBRL-formulae", linkrole, None,
                                          None))
                                     formulaArcFound = True
                                 if XbrlConst.isEuRenderingArcrole(
                                         arcrole
                                 ) and not euRenderingArcFound:
                                     baseSetKeys.append(
                                         ("EU-rendering", None, None, None))
                                     baseSetKeys.append(
                                         ("EU-rendering", linkrole, None,
                                          None))
                                     euRenderingArcFound = True
                                     self.modelXbrl.hasEuRendering = True
                                 for baseSetKey in baseSetKeys:
                                     self.modelXbrl.baseSets[
                                         baseSetKey].append(modelLink)
                                 arcrolesFound.add(arcrole)
                         elif xlinkType == "resource":
                             # create resource and make accessible by id for document
                             modelResource = ModelObject.createResource(
                                 self, linkElement)
                         if modelResource is not None:
                             if linkElement.hasAttribute("id"):
                                 self.idObjects[linkElement.getAttribute(
                                     "id")] = modelResource
                             modelLink.labeledResources[linkElement.getAttributeNS(XbrlConst.xlink, "label")] \
                                 .append(modelResource)
                         else:
                             XmlUtil.markIdAttributes(linkElement)
Example #54
0
 def resultIsTable(self):
     result = XmlUtil.descendant(self, None, "result")
     if result is not None:
         child = XmlUtil.child(result, None, "table")
         return child is not None and XmlUtil.text(child).endswith(".xml")
     return False
Example #55
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
Example #56
0
 def resultXbrlInstanceUri(self):
     resultInstance = XmlUtil.descendant(
         XmlUtil.descendant(self, None, "result"), None, "instance")
     if resultInstance is not None:
         return XmlUtil.text(resultInstance)
     return None
Example #57
0
 def fiscalYearEnd(self):
     yrEnd = XmlUtil.text(XmlUtil.descendant(self, edgr, "fiscalYearEnd"))
     if yrEnd and len(yrEnd) == 4:
         return "{0}-{1}".format(yrEnd[0:2], yrEnd[2:4])
     return None
Example #58
0
 def toURI(self):
     return XmlUtil.childAttr(self, XbrlConst.ver, "toURI", "value")
Example #59
0
 def versioningReportUri(self):
     return XmlUtil.text(XmlUtil.descendant(self, None, "versioningReport"))
Example #60
0
 def resultIsVersioningReport(self):
     return XmlUtil.descendant(XmlUtil.descendant(self, None, "result"), None, "versioningReport") is not None