def qn(self, name): if isinstance(name, QName): return name # if the name is a clark notation string if name[0] == '{': return qname(name) # else if the name contains a namespace prefix elif ':' in name: try: namespaces = self._namespaces except AttributeError: namespaces = self._namespaces = self.model.prefixedNamespaces return qname(name, namespaces) # else it is a local name else: try: local_name_to_qname = self._local_name_to_qname except AttributeError: local_name_to_qname = self._local_name_to_qname = collections.defaultdict( list) for qn_ in self.model.qnameConcepts: # type: QName local_name_to_qname[qn_.localName].append(qn_) qnames = local_name_to_qname[name] if len(qnames) > 1: raise ValueError( 'Multiple QNames for local name {}: {}'.format( name, qnames)) return qnames[0]
def copyNodes(parent, elts): from arelle.ModelValue import (qname) document = parent.ownerDocument xmlnsElement = document.documentElement for origElt in elts if hasattr(elts, '__iter__') else (elts, ): copyElt = document.createElementNS( origElt.namespaceURI, addQnameValue(document.documentElement, qname(origElt))) parent.appendChild(copyElt) for i in range(len(origElt.attributes)): origAttr = origElt.attributes.item(i) if origAttr.prefix and origAttr.namespaceURI: copyElt.setAttributeNS( origAttr.namespaceURI, addQnameValue(document.documentElement, qname(origAttr.namespaceURI, origAttr.name)), origAttr.value) else: copyElt.setAttribute(origAttr.name, origAttr.value) textContentSet = False if hasattr(origElt, "xValue"): from arelle.ModelValue import (QName) if isinstance(origElt.xValue, QName): copyElt.appendChild( document.createTextNode( addQnameValue(document.documentElement, origElt.xValue))) textContentSet = True for childNode in origElt.childNodes: if (childNode.nodeType == 3 or childNode.nodeType == 4) and not textContentSet: copyElt.appendChild( document.createTextNode(childNode.nodeValue)) elif childNode.nodeType == 1: copyNodes(copyElt, childNode)
def loadNonNegativeFacts(modelXbrl): signwarnings = loadDqc0015signwarningRules(modelXbrl) concepts = set() excludedMembers = set() excludedMemberStrings = set() excludedAxesMembers = defaultdict(set) for modelDocument in modelXbrl.urlDocs.values(): ns = modelDocument.targetNamespace # set up non neg lookup by full NS for abbrNs in (abbreviatedNamespace(ns), abbreviatedWildNamespace(ns)): nsMatch = False for exName, exSet, isQName in (("conceptNames", concepts, True), ("excludedMemberNames", excludedMembers, True), ("excludedMemberStrings", excludedMemberStrings, False)): for localName in signwarnings[exName].get(abbrNs, ()): exSet.add(qname(ns, localName) if isQName else localName) nsMatch = True for localDimName, localMemNames in signwarnings["excludedAxesMembers"].get(abbrNs, EMPTY_DICT).items(): for localMemName in localMemNames: excludedAxesMembers[qname(ns, localDimName)].add(qname(ns, localMemName) if localMemName != "*" else "*") nsMatch = True if nsMatch: break # use explicit year rules if available, else generic year rules return attrdict(concepts=concepts, excludedAxesMembers=excludedAxesMembers, excludedMembers=excludedMembers, excludedMemberNamesPattern=re.compile("|".join(excludedMemberStrings), re.IGNORECASE) if excludedMemberStrings else None)
def copyNodes(parent, elts): from arelle.ModelValue import (qname) document = parent.ownerDocument xmlnsElement = document.documentElement for origElt in elts if hasattr(elts, '__iter__') else (elts,): copyElt = document.createElementNS(origElt.namespaceURI, addQnameValue(document.documentElement, qname(origElt))) parent.appendChild(copyElt) for i in range(len(origElt.attributes)): origAttr = origElt.attributes.item(i) if origAttr.prefix and origAttr.namespaceURI: copyElt.setAttributeNS(origAttr.namespaceURI, addQnameValue(document.documentElement, qname(origAttr.namespaceURI,origAttr.name)), origAttr.value) else: copyElt.setAttribute(origAttr.name, origAttr.value) textContentSet = False if hasattr(origElt, "xValue"): from arelle.ModelValue import (QName) if isinstance(origElt.xValue,QName): copyElt.appendChild(document.createTextNode( addQnameValue(document.documentElement, origElt.xValue))) textContentSet = True for childNode in origElt.childNodes: if (childNode.nodeType == 3 or childNode.nodeType == 4) and not textContentSet: copyElt.appendChild(document.createTextNode(childNode.nodeValue)) elif childNode.nodeType == 1: copyNodes(copyElt,childNode)
def loadSECtransforms(customTransforms): ixtSEC = "http://www.sec.gov/inlineXBRL/transformation/2015-08-30" customTransforms.update({ qname(ixtSEC, "ixt-sec:duryear"): duryear, qname(ixtSEC, "ixt-sec:durmonth"): durmonth, qname(ixtSEC, "ixt-sec:durweek"): durweek, qname(ixtSEC, "ixt-sec:durday"): durday, qname(ixtSEC, "ixt-sec:durhour"): durhour })
def createFacts(facts, parent): for fact in facts: if fact.isItem: # HF does not de-duplicate, which is currently-desired behavior modelConcept = fact.concept # isItem ensures concept is not None attrs = {"contextRef": fact.contextID} if fact.id: attrs["id"] = fact.id if fact.isNumeric: attrs["unitRef"] = fact.unitID if fact.get("decimals"): attrs["decimals"] = fact.get("decimals") if fact.get("precision"): attrs["precision"] = fact.get("precision") if fact.isNil: attrs[XbrlConst.qnXsiNil] = "true" text = None elif (not (modelConcept.baseXsdType == "token" and modelConcept.isEnumeration) and fact.xValid): text = fact.xValue # may need a special case for QNames (especially if prefixes defined below root) else: text = fact.textValue for attrName, attrValue in fact.items(): if attrName.startswith("{"): attrs[qname( attrName, fact.nsmap )] = attrValue # using qname allows setting prefix in extracted instance newFact = targetInstance.createFact(fact.qname, attributes=attrs, text=text, parent=parent) # if fact.isFraction, create numerator and denominator newFactForOldObjId[fact.objectIndex] = newFact if filingFiles is not None and fact.concept is not None and fact.concept.isTextBlock: # check for img and other filing references so that referenced files are included in the zip. for xmltext in [text] + CDATApattern.findall(text): try: for elt in XML("<body>\n{0}\n</body>\n".format( xmltext)).iter(): addLocallyReferencedFile(elt, filingFiles) except (XMLSyntaxError, UnicodeDecodeError): pass # TODO: Why ignore UnicodeDecodeError? elif fact.isTuple: attrs = {} if fact.id: attrs["id"] = fact.id if fact.isNil: attrs[XbrlConst.qnXsiNil] = "true" for attrName, attrValue in fact.items(): if attrName.startswith("{"): attrs[qname(attrName, fact.nsmap)] = attrValue newTuple = targetInstance.createFact(fact.qname, attributes=attrs, parent=parent) newFactForOldObjId[fact.objectIndex] = newTuple createFacts(fact.modelTupleFacts, newTuple)
def schemaDescendantsNames(element, descendantNamespaceURI, descendantLocalName, qnames=None): from arelle.ModelValue import (qname) if qnames is None: qnames = set() for child in element.getElementsByTagNameNS(descendantNamespaceURI, descendantLocalName): if child.hasAttribute("name"): # need to honor attribute/element form default qnames.add(qname(targetNamespace(element), child.getAttribute("name"))) elif child.hasAttribute("ref"): qnames.add(qname(element, child.getAttribute("ref"))) return qnames
def schemaDescendantsNames(element, descendantNamespaceURI, descendantLocalName, qnames=None): if qnames is None: qnames = set() for child in element.iterdescendants(tag="{{{0}}}{1}".format(descendantNamespaceURI,descendantLocalName)): if isinstance(child,ModelObject): if child.get("name"): # need to honor attribute/element form default qnames.add(qname(targetNamespace(element), child.get("name"))) elif child.get("ref"): qnames.add(qname(element, child.get("ref"))) return qnames
def loadNonNegativeFacts(modelXbrl, dqcRules, ugtRels): # for us-gaap newer than 2020 use DQCRT non-negative facts. if dqcRules and ugtRels: # not used before 2020 if usgaapYear( modelXbrl) == "2020" and "dqcrt-2021-usgaap-2020" not in ( modelXbrl.modelManager.disclosureSystem.options or ""): dqcRules.clear() # remove dqc rules return ugtRels[ "DQC.US.0015"] # use 20.1 2020 nonNegFacts test and warning return None # use all available DQCRT tests # for us-gaap < dqcyear use EFM non-negative warning insead of DQC rule _file = openFileStream(modelXbrl.modelManager.cntlr, resourcesFilePath(modelXbrl.modelManager, "signwarnings.json"), 'rt', encoding='utf-8') signwarnings = json.load(_file) # {localName: date, ...} _file.close() concepts = set() excludedMembers = set() excludedMemberStrings = set() excludedAxesMembers = defaultdict(set) for modelDocument in modelXbrl.urlDocs.values(): ns = modelDocument.targetNamespace # set up non neg lookup by full NS for abbrNs in (abbreviatedNamespace(ns), abbreviatedNamespace(ns, WILD)): nsMatch = False for exName, exSet, isQName in (("conceptNames", concepts, True), ("excludedMemberNames", excludedMembers, True), ("excludedMemberStrings", excludedMemberStrings, False)): for localName in signwarnings[exName].get(abbrNs, ()): exSet.add(qname(ns, localName) if isQName else localName) nsMatch = True for localDimName, localMemNames in signwarnings[ "excludedAxesMembers"].get(abbrNs, EMPTY_DICT).items(): for localMemName in localMemNames: excludedAxesMembers[qname(ns, localDimName)].add( qname(ns, localMemName) if localMemName != "*" else "*" ) nsMatch = True if nsMatch: break # use explicit year rules if available, else generic year rules return attrdict(concepts=concepts, excludedAxesMembers=excludedAxesMembers, excludedMembers=excludedMembers, excludedMemberNamesPattern=re.compile( "|".join(excludedMemberStrings), re.IGNORECASE) if excludedMemberStrings else None)
def loadSECtransforms(customTransforms, *args, **kwargs): ixtSEC = "http://www.sec.gov/inlineXBRL/transformation/2015-08-31" customTransforms.update({ qname(ixtSEC, "ixt-sec:duryear"): duryear, qname(ixtSEC, "ixt-sec:durmonth"): durmonth, qname(ixtSEC, "ixt-sec:durweek"): durweek, qname(ixtSEC, "ixt-sec:durday"): durday, qname(ixtSEC, "ixt-sec:durhour"): durhour, qname(ixtSEC, "ixt-sec:numinf"): numinf, qname(ixtSEC, "ixt-sec:numneginf"): numneginf, qname(ixtSEC, "ixt-sec:numnan"): numnan, qname(ixtSEC, "ixt-sec:numwordsen"): numwordsen, qname(ixtSEC, "ixt-sec:durwordsen"): durwordsen })
def isStandardExtLinkQname(qName): return qName in ( qname("{http://www.xbrl.org/2003/linkbase}definitionLink"), qname("{http://www.xbrl.org/2003/linkbase}calculationLink"), qname("{http://www.xbrl.org/2003/linkbase}presentationLink"), qname("{http://www.xbrl.org/2003/linkbase}labelLink"), qname("{http://www.xbrl.org/2003/linkbase}referenceLink"), qname("{http://www.xbrl.org/2003/linkbase}footnoteLink"), qname("{http://www.xbrl.org/2003/linkbase}label"), qname("{http://www.xbrl.org/2003/linkbase}footnote"), qname("{http://www.xbrl.org/2003/linkbase}reference"))
def schemaDescendantsNames(element, descendantNamespaceURI, descendantLocalName, qnames=None): from arelle.ModelValue import (qname) if qnames is None: qnames = set() for child in element.getElementsByTagNameNS(descendantNamespaceURI, descendantLocalName): if child.hasAttribute("name"): # need to honor attribute/element form default qnames.add( qname(targetNamespace(element), child.getAttribute("name"))) elif child.hasAttribute("ref"): qnames.add(qname(element, child.getAttribute("ref"))) return qnames
def loadNonNegativeFacts(modelXbrl): _file = openFileStream(modelXbrl.modelManager.cntlr, resourcesFilePath(modelXbrl.modelManager, "signwarnings.json"), 'rt', encoding='utf-8') signwarnings = json.load(_file) # {localName: date, ...} _file.close() concepts = set() excludedAxesMembers = defaultdict(set) for modelDocument in modelXbrl.urlDocs.values(): ns = modelDocument.targetNamespace # set up non neg lookup by full NS for abbrNs in (abbreviatedNamespace(ns), abbreviatedWildNamespace(ns)): for localName in signwarnings["conceptNames"].get(abbrNs, ()): concepts.add(qname(ns, localName)) for localDimName, localMemNames in signwarnings["excludedAxesMembers"].get(abbrNs, EMPTY_DICT).items(): for localMemName in localMemNames: excludedAxesMembers[qname(ns, localDimName)].add(qname(ns, localMemName) if localMemName != "*" else None) return attrdict(concepts=concepts, excludedAxesMembers=excludedAxesMembers)
def loadNonNegativeFacts(modelXbrl): _file = openFileStream(modelXbrl.modelManager.cntlr, resourcesFilePath(modelXbrl.modelManager, "signwarnings.json"), 'rt', encoding='utf-8') signwarnings = json.load(_file) # {localName: date, ...} _file.close() concepts = set() excludedAxesMembers = defaultdict(set) for modelDocument in modelXbrl.urlDocs.values(): ns = modelDocument.targetNamespace # set up non neg lookup by full NS for abbrNs in (abbreviatedNamespace(ns), abbreviatedWildNamespace(ns)): for localName in signwarnings["conceptNames"].get(abbrNs, ()): concepts.add(qname(ns, localName)) for localDimName, localMemNames in signwarnings["excludedAxesMembers"].get(abbrNs, EMPTY_DICT).items(): for localMemName in localMemNames: excludedAxesMembers[qname(ns, localDimName)].add(qname(ns, localMemName) if localMemName != "*" else "*") return attrdict(concepts=concepts, excludedAxesMembers=excludedAxesMembers)
def copyNodes(parent, elts): modelDocument = parent.modelDocument for origElt in elts if isinstance(elts, (tuple, list, set)) else (elts, ): addQnameValue(modelDocument, origElt.elementQname) copyElt = modelDocument.parser.makeelement(origElt.tag) copyElt.init(modelDocument) parent.append(copyElt) for attrTag, attrValue in origElt.items(): qn = qname(attrTag, noPrefixIsNoNamespace=True) prefix = xmlnsprefix(origElt, qn.namespaceURI) if prefix: setXmlns(modelDocument, prefix, qn.namespaceURI) copyElt.set(attrTag, attrValue) else: copyElt.set(attrTag, attrValue) textContentSet = False if hasattr(origElt, "xValue"): if isinstance(origElt.xValue, QName): copyElt.text = addQnameValue(modelDocument, origElt.xValue) textContentSet = True if not textContentSet: text = origElt.text if text is not None: text = text.strip() # don't copy whitespace text if text: copyElt.text = text for childNode in origElt: if isinstance(childNode, ModelObject): copyNodes(copyElt, childNode)
def lookup(self, document, proxyElement): # check if proxyElement's namespace is not known ns, sep, ln = proxyElement.tag.partition("}") if sep: ns = ns[1:] else: ln = ns ns = None if (ns and ns not in self.discoveryAttempts and ns not in self.modelXbrl.namespaceDocs): # is schema loadable? requires a schemaLocation from arelle import XmlUtil, ModelDocument relativeUrl = XmlUtil.schemaLocation(proxyElement, ns) self.discoveryAttempts.add(ns) if relativeUrl: doc = ModelDocument.loadSchemalocatedSchema(self.modelXbrl, proxyElement, relativeUrl, ns, self.baseUrl) modelObjectClass = self.modelXbrl.matchSubstitutionGroup( qname(ns, ln), elementSubstitutionModelClass) if modelObjectClass is not None: return modelObjectClass else: xlinkType = proxyElement.get("{http://www.w3.org/1999/xlink}type") if xlinkType == "extended": return ModelLink elif xlinkType == "locator": return ModelLocator elif xlinkType == "resource": return ModelResource return ModelObject
def get_dei_facts(model_xbrl): """XBRLデータから会社・書類情報を取得する""" qname_prefix = "jpdei_cor" ns = model_xbrl.prefixedNamespaces[qname_prefix] dict_facts = {} # 【備考】: Qname指定でfactを取得 # ModelXbrlクラスのインスタンスのfactsBy*属性(辞書型)にfactが格納されている。 # このうち、QnameをキーとするfactsByQnameを使用する。 # 但し、factsByQnameのキーはQname文字列ではなく、Qnameクラスのインスタンス。 # 文字列からQnameインスタンスを作成するために、qname関数を使用する。 for localname in DEI_COLS: facts = model_xbrl.factsByQname[qname( ns, name=f"{qname_prefix}:{localname}")] if (not facts) or (len(facts) > 1): print(f"【想定外】1つのXBRL内に{qname_prefix}:{localname}のfactが複数存在します。") sys.exit() fact = list(facts)[0] if localname == ACCOUNTING_STD_ELM_NAME: if fact.value != "Japan GAAP": print(f"会計基準: {fact.value} 処理対象外") return None if localname == DOC_TYPE_ELM_NAME: if fact.value != TGT_DOC_TYPE: print(f"提出書類の様式: {fact.value} 処理対象外") return None if localname == EDINET_CD_ELM_NAME: dict_facts[EDINETCD_COL] = fact.value else: dict_facts[fact.concept.label()] = fact.value return pd.DataFrame([dict_facts])
def fromConceptQname(self): fromConcept = XmlUtil.child(self.element, XbrlConst.vercb, "fromConcept") if fromConcept and fromConcept.hasAttribute("name"): return qname(fromConcept, fromConcept.getAttribute("name")) else: return None
def variableReferences(exprStack, varRefSet, element, rangeVars=None): localRangeVars = [] if rangeVars is None: rangeVars = [] from arelle.ModelValue import qname for p in exprStack: if isinstance(p, ProgHeader): element = p.element elif isinstance(p,VariableRef): var = qname(element, p.name, noPrefixIsNoNamespace=True) if var not in rangeVars: varRefSet.add(var) elif isinstance(p,OperationDef): variableReferences(p.args, varRefSet, element, rangeVars) elif isinstance(p,Expr): variableReferences(p.expr, varRefSet, element, rangeVars) elif isinstance(p,RangeDecl): var = p.rangeVar.name rangeVars.append(var) localRangeVars.append(var) variableReferences(p.bindingSeq, varRefSet, element, rangeVars) elif hasattr(p, '__iter__') and not isinstance(p, _STR_BASE): variableReferences(p, varRefSet, element, rangeVars) for localRangeVar in localRangeVars: if localRangeVar in rangeVars: rangeVars.remove(localRangeVar)
def typedDimElt(s): # add xmlns into s for known qnames tag, angleBrkt, rest = s[1:].partition('>') text, angleBrkt, rest = rest.partition("<") qn = qname(tag, prefixedNamespaces) # a modelObject xml element is needed for all of the instance functions to manage the typed dim return addChild(modelXbrl.modelDocument, qn, text=text, appendChild=False)
def my_fn_PDxEV(xc, p, contextItem, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() PDseq = args[0] if isinstance(args[0],(list,tuple)) else (args[0],) EVseq = args[1] if isinstance(args[1],(list,tuple)) else (args[1],) dimQname = qname("{http://www.example.com/wgt-avg}ExposuresDimension") PDxEV = [] for pd in PDseq: if pd.context is not None: pdDim = pd.context.dimValue(dimQname) for ev in EVseq: if ev.context is not None: evDim = ev.context.dimValue(dimQname) if pdDim is not None and isinstance(pdDim,ModelDimensionValue): dimEqual = pdDim.isEqualTo(evDim, equalMode=XbrlUtil.S_EQUAL2) elif evDim is not None and isinstance(evDim,ModelDimensionValue): dimEqual = evDim.isEqualTo(pdDim, equalMode=XbrlUtil.S_EQUAL2) else: dimEqual = (pdDim == evDim) if dimEqual: pdX = pd.xValue evX = ev.xValue # type promotion required if isinstance(pdX,Decimal) and isinstance(evX,float): pdX = float(pdX) elif isinstance(evX,Decimal) and isinstance(pdX,float): pdX = float(evX) PDxEV.append(pdX * evX) break return PDxEV
def executeCallTest(val, name, callTuple, testTuple): if callTuple: XPathParser.initializeParser(val) try: val.modelXbrl.modelManager.showStatus(_("Executing call")) callExprStack = XPathParser.parse(val, callTuple[0], callTuple[1], name + " call", Trace.CALL) xpathContext = XPathContext.create(val.modelXbrl, sourceElement=callTuple[1]) result = xpathContext.evaluate(callExprStack) xpathContext.inScopeVars[qname('result',noPrefixIsNoNamespace=True)] = result val.modelXbrl.error( _("{0} result {1}").format( name, result), "info", "formula:trace") if testTuple: val.modelXbrl.modelManager.showStatus(_("Executing test")) testExprStack = XPathParser.parse(val, testTuple[0], testTuple[1], name + " test", Trace.CALL) testResult = xpathContext.effectiveBooleanValue( None, xpathContext.evaluate(testExprStack) ) val.modelXbrl.error( _("Test {0} result {1}").format( name, testResult), "info" if testResult else "err", "cfcn:testPass" if testResult else "cfcn:testFail") except XPathContext.XPathException as err: val.modelXbrl.error( _("{0} evaluation error: {1} \n{2}").format(name, err.message, err.sourceErrorIndication), "err", err.code) val.modelXbrl.modelManager.showStatus(_("ready"), 2000)
def variableReferences(exprStack, varRefSet, element, rangeVars=None): localRangeVars = [] if rangeVars is None: rangeVars = [] from arelle.ModelValue import qname for p in exprStack: if isinstance(p, ProgHeader): element = p.element elif isinstance(p, VariableRef): var = qname(element, p.name, noPrefixIsNoNamespace=True) if var not in rangeVars: varRefSet.add(var) elif isinstance(p, OperationDef): variableReferences(p.args, varRefSet, element, rangeVars) elif isinstance(p, Expr): variableReferences(p.expr, varRefSet, element, rangeVars) elif isinstance(p, RangeDecl): var = p.rangeVar.name rangeVars.append(var) localRangeVars.append(var) variableReferences(p.bindingSeq, varRefSet, element, rangeVars) elif hasattr(p, "__iter__") and not isinstance(p, _STR_BASE): variableReferences(p, varRefSet, element, rangeVars) for localRangeVar in localRangeVars: if localRangeVar in rangeVars: rangeVars.remove(localRangeVar)
def copyNodes(parent, elts): modelDocument = parent.modelDocument for origElt in elts if isinstance(elts, (tuple,list,set)) else (elts,): addQnameValue(modelDocument, origElt.elementQname) copyElt = modelDocument.parser.makeelement(origElt.tag) copyElt.init(modelDocument) parent.append(copyElt) for attrTag, attrValue in origElt.items(): qn = qname(attrTag, noPrefixIsNoNamespace=True) prefix = xmlnsprefix(origElt, qn.namespaceURI) if prefix: setXmlns(modelDocument, prefix, qn.namespaceURI) copyElt.set(attrTag, attrValue) else: copyElt.set(attrTag, attrValue) textContentSet = False if hasattr(origElt, "xValue"): if isinstance(origElt.xValue,QName): copyElt.text = addQnameValue(modelDocument, origElt.xValue) textContentSet = True if not textContentSet: text = origElt.text if text is not None: text = text.strip() # don't copy whitespace text if text: copyElt.text = text for childNode in origElt: if isinstance(childNode,ModelObject): copyNodes(copyElt,childNode)
def escapedNode(elt, start, empty, ixEscape, ixResolveUris): if elt.namespaceURI in ixbrlAll: return '' # do not yield XML for nested facts if ixResolveUris: uriAttrs = htmlEltUriAttrs.get(elt.qname.localName, ()) else: uriAttrs = () s = ['<'] if not start and not empty: s.append('/') if ixEscape == "html" and elt.qname.namespaceURI == xhtml: s.append(elt.qname.localName) # force xhtml prefix to be default else: s.append(str(elt.qname)) if start or empty: if elt.localName == "object" and elt.get( "codebase"): # resolve codebase before other element names elt.set("codebase", resolveHtmlUri(elt, "codebase"), elt.get("codebase")) for n, v in sorted(elt.items(), key=lambda item: item[0]): if n in uriAttrs: v = resolveHtmlUri(elt, n, v).replace( " ", "%20" ) # %20 replacement needed for conformance test passing s.append(' {0}="{1}"'.format( qname(elt, n), v.replace("&", "&").replace('"', '"'))) if not start and empty: s.append('/') s.append('>') return ''.join(s)
def element_name(xc, p, args, elementParent=False): if len(args) != 1: raise XPathContext.FunctionNumArgs() modelRel = anytypeArg(xc, args, 0, "arelle:ModelRelationship", None) if modelRel is None: raise XPathContext.FunctionArgType(1,"arelle:modelRelationship") element = modelRel.arcElement if elementParent: element = element.getparent() return qname(element)
def my_fn_PDxEV(xc, p, contextItem, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() PDseq = args[0] if isinstance(args[0], (list, tuple)) else (args[0], ) EVseq = args[1] if isinstance(args[1], (list, tuple)) else (args[1], ) dimQname = qname("{http://www.example.com/wgt-avg}ExposuresDimension") PDxEV = [] for pd in PDseq: if pd.context is not None: pdDim = pd.context.dimValue(dimQname) for ev in EVseq: if ev.context is not None: evDim = ev.context.dimValue(dimQname) if pdDim is not None and isinstance( pdDim, ModelDimensionValue): dimEqual = pdDim.isEqualTo(evDim, equalMode=XbrlUtil.S_EQUAL2) elif evDim is not None and isinstance( evDim, ModelDimensionValue): dimEqual = evDim.isEqualTo(pdDim, equalMode=XbrlUtil.S_EQUAL2) else: dimEqual = (pdDim == evDim) if dimEqual: PDxEV.append(pd.xValue * ev.xValue) break return PDxEV
def segmentScenario(self, element, contextId, name, sect, topLevel=True): if topLevel: if element is None: return # nothing to check else: if element.namespaceURI == XbrlConst.xbrli: self.modelXbrl.error( _("Context {0} {1} cannot have xbrli element {2}").format( contextId, name, element.tagName), "err", "xbrl.{0}:{1}XbrliElement".format(sect, name)) else: concept = self.modelXbrl.qnameConcepts.get(qname(element)) if concept and (concept.isItem or concept.isTuple): self.modelXbrl.error( _("Context {0} {1} cannot have item or tuple element {2}" ).format(contextId, name, element.tagName), "err", "xbrl.{0}:{1}ItemOrTuple".format(sect, name)) hasChild = False for child in element.childNodes: if child.nodeType == 1: self.segmentScenario(child, contextId, name, sect, topLevel=False) hasChild = True if topLevel and not hasChild: self.modelXbrl.error( _("Context {0} {1} cannot be empty").format(contextId, name), "err", "xbrl.{0}:{1}Empty".format(sect, name))
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
def validateXbrlStart(val, parameters=None, *args, **kwargs): val.validateHMRCplugin = val.validateDisclosureSystem and getattr(val.disclosureSystem, "HMRCplugin", False) if not (val.validateHMRCplugin): return if parameters: p = parameters.get(qname("type",noPrefixIsNoNamespace=True)) if p and len(p) == 2: # override implicit type paramType = p[1].lower() val.isAccounts = paramType == "accounts" val.isComputation = paramType == "computation" if not hasattr(val, "isAccounts"): val.isComputation = any(compTxmyNamespacePattern.match(doc.targetNamespace) for doc in val.modelXbrl.urlDocs.values() if doc.targetNamespace) val.isAccounts = not val.isComputation val.txmyType = None for doc in val.modelXbrl.modelDocument.referencesDocument: ns = doc.targetNamespace if ns: if ns.startswith("http://www.xbrl.org/uk/char/"): val.txmyType = "charities" elif ns.startswith("http://www.xbrl.org/uk/gaap/"): val.txmyType = "ukGAAP" elif ns.startswith("http://www.xbrl.org/uk/ifrs/"): val.txmyType = "ukIFRS" elif ns.startswith("http://xbrl.frc.org.uk/"): val.txmyType = "FRS" else: continue break if val.txmyType: val.modelXbrl.debug("debug", "HMRC taxonomy type %(taxonomyType)s", modelObject=val.modelXbrl, taxonomyType=val.txmyType) else: val.modelXbrl.error("HMRC.TBD", _("No recognized standard taxonomy (UK GAAP, UK IFRS, Charity, or FRS)."), modelObject=val.modelXbrl)
def my_fn_PDxEV(xc, p, contextItem, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() PDseq = flattenSequence(args[0]) EVseq = flattenSequence(args[1]) dimQname = qname("{http://www.example.com/wgt-avg}ExposuresDimension") PDxEV = [] for pd in PDseq: if pd.context is not None: pdDim = pd.context.dimValue(dimQname) for ev in EVseq: if ev.context is not None: evDim = ev.context.dimValue(dimQname) if pdDim is not None and isinstance(pdDim,ModelDimensionValue): dimEqual = pdDim.isEqualTo(evDim, equalMode=XbrlUtil.S_EQUAL2) elif evDim is not None and isinstance(evDim,ModelDimensionValue): dimEqual = evDim.isEqualTo(pdDim, equalMode=XbrlUtil.S_EQUAL2) else: dimEqual = (pdDim == evDim) if dimEqual: pdX = pd.xValue evX = ev.xValue # type promotion required if isinstance(pdX,Decimal) and isinstance(evX,float): pdX = float(pdX) elif isinstance(evX,Decimal) and isinstance(pdX,float): pdX = float(evX) PDxEV.append(pdX * evX) break return PDxEV
def get_tgt_fact(model_xbrl, is_consolidated, ns, qname_prefix, top_str_for_contextid, mcpt): """指定したModelObjectのfact を取得""" # 【備考】1つの要素に対し、コンテキスト・ユニットの異なる複数のfactが存在し得る。 # コンテキストIDについては、報告書インスタンス作成ガイドライン:5-4-5 コンテキストの設定例 参照 # 【注意】有報では時点型/期間型どちらも当期を表す接頭辞はCurrentYearで同じだが # 四半期報告書は時点型はCurrentQuarter、期間型はCurrentQuarterとCurrentYTD(累積)がある。 # 貸借対照表は対象期末(対象期間終了日)時点の状態を表すので勘定科目は時点型(一応periodTypeを取得) # EDINET勘定科目リスト 参照 contextid = f"{top_str_for_contextid}{mcpt.periodType.capitalize()}" if not is_consolidated: contextid += "_NonConsolidatedMember" facts = model_xbrl.factsByQname[qname( ns, name=f"{qname_prefix}:{mcpt.qname.localName}")] for fact in facts: # 対象期の財務情報かつユニットが日本円のfactを取得する if (fact.contextID == contextid) and (fact.unitID == "JPY"): return fact.value # TODO: プレフィックス対応 # 提出者が独自定義したタクソノミスキーマの要素はjppfs_corではないため # 現状プログラムではfactを取得できない。 # 欲しい情報はとれているので、一旦ペンディング。 # 【備考】提出者別タクソノミ作成ガイドライン > 「要素の定義」参照 print("abstract==Falseの勘定科目のfactを取得できませんでした。") print(f"{qname_prefix}:{mcpt.qname.localName}") return None
def determineTestStatus(self, modelTestcaseVariation, modelUnderTest): numErrors = len(modelUnderTest.errors) expected = modelTestcaseVariation.expected if expected == "valid": if numErrors == 0: status = "pass" else: status = "fail" elif expected == "invalid": if numErrors == 0: status = "fail" else: status = "pass" elif expected is None and numErrors == 0: status = "pass" elif isinstance(expected,(QName,str,dict)): # string or assertion id counts dict status = "fail" for testErr in modelUnderTest.errors: if isinstance(expected,QName) and isinstance(testErr,str): errPrefix, sep, errLocalName = testErr.partition(":") if ((not sep and errPrefix == expected.localName) or (expected == qname(XbrlConst.errMsgPrefixNS.get(errPrefix), errLocalName)) or # XDT xml schema tests expected results (expected.namespaceURI == XbrlConst.xdtSchemaErrorNS and errPrefix == "xmlSchema")): status = "pass" break elif type(testErr) == type(expected): if (testErr == expected or (expected == "EFM.6.03.04" and testErr.startswith("xmlSchema:")) or (expected == "EFM.6.03.05" and (testErr.startswith("xmlSchema:") or testErr == "EFM.5.2.1.1")) or (expected == "EFM.6.04.03" and (testErr.startswith("xmlSchema:") or testErr.startswith("utr:") or testErr.startswith("xbrl.") or testErr.startswith("xlink:"))) or (expected == "EFM.6.05.35" and testErr.startswith("utr:"))): status = "pass" break if expected == "EFM.6.03.02" or expected == "EFM.6.03.08": # 6.03.02 is not testable status = "pass" if not modelUnderTest.errors and status == "fail": if modelTestcaseVariation.assertions: if modelTestcaseVariation.assertions == expected: status = "pass" # passing was previously successful and no further errors elif (isinstance(expected,dict) and # no assertions fired, are all the expected zero counts? all(countSatisfied == 0 and countNotSatisfied == 0 for countSatisfied, countNotSatisfied in expected.values())): status = "pass" # passes due to no counts expected else: status = "fail" modelTestcaseVariation.status = status if numErrors > 0: modelTestcaseVariation.actual = [] # put error codes first, sorted, then assertion result (dict's) for error in modelUnderTest.errors: if isinstance(error,dict): # asserion results modelTestcaseVariation.assertions = error else: # error code results modelTestcaseVariation.actual.append(error) modelTestcaseVariation.actual.sort(key=lambda d: str(d)) for error in modelUnderTest.errors: if isinstance(error,dict): modelTestcaseVariation.actual.append(error)
def element_name(xc, p, args, elementParent=False): if len(args) != 1: raise XPathContext.FunctionNumArgs() modelRel = anytypeArg(xc, args, 0, "arelle:ModelRelationship", None) if not modelRel: raise XPathContext.FunctionArgType(1, "arelle:modelRelationship") element = modelRel.element if elementParent: element = element.parentNode return qname(element)
def measure_name(xc, p, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() if len(args[0]) != 1: raise XPathContext.FunctionArgType(1,"xbrl:measure") unit = args[0][0] if isinstance(unit,ModelObject) and \ unit.localName == "measure" and unit.namespaceURI == XbrlConst.xbrli: return qname(unit, XmlUtil.text(unit)) raise XPathContext.FunctionArgType(1,"xbrl:unit")
def measure_name(xc, p, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() if len(args[0]) != 1: raise XPathContext.FunctionArgType(1, "xbrl:measure") unit = args[0][0] if isinstance(unit,xml.dom.Node) and unit.nodeType == 1 and \ unit.localName == "measure" and unit.namespaceURI == XbrlConst.xbrli: return qname(unit, XmlUtil.text(unit)) raise XPathContext.FunctionArgType(1, "xbrl:unit")
def fromConceptQname(self): fromConcept = XmlUtil.child( self, None, "fromConcept" ) # can be vercu or vercb, schema validation will assure right elements if fromConcept is not None and fromConcept.get("name"): return qname(fromConcept, fromConcept.get("name")) else: return None
def lookup(self, node_type, document, ns, ln): # node_type is "element", "comment", "PI", or "entity" if node_type == "element": if ns == XbrlConst.xsd: if self.type is None: self.type = SCHEMA if ln == "element": return ModelConcept elif ln == "attribute": return ModelAttribute elif ln == "attributeGroup": return ModelAttributeGroup elif ln == "complexType" or ln == "simpleType": return ModelType elif ln == "enumeration": return ModelEnumeration elif ns == XbrlConst.link: if self.type is None: self.type = LINKBASE if ln == "roleType" or ln == "arcroleType": return ModelRoleType elif ns == "http://edgar/2009/conformance": # don't force loading of test schema if ln == "variation": return ModelTestcaseVariation else: return ModelObject elif ln == "testcase" and ( ns is None or ns in ("http://edgar/2009/conformance",) or ns.startswith("http://xbrl.org/")): return ModelObject elif ln == "variation" and ( ns is None or ns in ("http://edgar/2009/conformance",) or ns.startswith("http://xbrl.org/")): return ModelTestcaseVariation elif ns == XbrlConst.ver: if self.type is None: self.type = VERSIONINGREPORT elif ns == "http://dummy": return etree.ElementBase if self.type is None and ln == "rss": self.type = RSSFEED elif self.type == RSSFEED: if ln == "item": return ModelRssItem else: return ModelObject # match specific element types or substitution groups for types return self.modelXbrl.matchSubstitutionGroup( qname(ns, ln), elementSubstitutionModelClass) elif node_type == "comment": from arelle.ModelObject import ModelComment return ModelComment elif node_type == "PI": return etree.PIBase elif node_type == "entity": return etree.EntityBase
def setOptions(self): # set formula options for checkbox in self.checkboxes: setattr(self.options, checkbox.attr, checkbox.value) self.options.parameters = {} for paramCells in self.gridCells: qnameCell, typeCell, valueCell = paramCells if qnameCell.value != "" and valueCell.value != "": self.options.parameters[qname(qnameCell.value)] = valueCell.value
def node_name(xc, p, contextItem, args): node = nodeArg(xc, args, 0, "node()?", missingArgFallback=contextItem, emptyFallback=()) if node != (): return qname(node) return ()
def __init__(self, sourceStr, loc, qnameToken): super(astQnameLiteral, self).__init__(sourceStr, loc) try: self.value = qname(qnameToken, xmlns, prefixException=KeyError, noPrefixIsNoNamespace=(qnameToken.lower() in functionImplementation or qnameToken in reservedWords)) except KeyError: raise PrefixError(qnameToken)
def setOptions(self): # set formula options for checkbox in self.checkboxes: setattr(self.options, checkbox.attr, checkbox.value) self.options.parameters = {} for paramCells in self.gridCells: qnameCell, typeCell, valueCell = paramCells if qnameCell.value != "" and valueCell.value != "": self.options.parameters[qname( qnameCell.value)] = valueCell.value
def coveredAspect(self, structuralNode=None): try: return self._coveredAspect except AttributeError: coveredAspect = self.get("coveredAspect") if coveredAspect in coveredAspectToken: self._coveredAspect = coveredAspectToken[coveredAspect] else: # must be a qname self._coveredAspect = qname(self, coveredAspect) return self._coveredAspect
def validate(modelXbrl, elt, recurse=True, attrQname=None): if not hasattr(elt, "xValid"): text = XmlUtil.text(elt) qnElt = qname(elt) modelConcept = modelXbrl.qnameConcepts.get(qnElt) if modelConcept: baseXsdType = modelConcept.baseXsdType if len(text) == 0 and modelConcept.default is not None: text = modelConcept.default elif qnElt == XbrlConst.qnXbrldiExplicitMember: # not in DTS baseXsdType = "QName" else: baseXsdType = None if attrQname is None: validateNode(modelXbrl, elt, elt, baseXsdType, text) # validate attributes # find missing attributes for default values for i in range(len(elt.attributes)): attr = elt.attributes.item(i) attrNsURI = attr.namespaceURI if (attr.name not in ("xmlns") and attr.prefix != "xmlns"): if attrNsURI: qn = qname(attrNsURI, attr.localName) else: qn = qname(attr.localName) if attrQname and attrQname != qn: continue baseXsdAttrType = None if modelConcept: baseXsdAttrType = modelConcept.baseXsdAttrType( qn) if modelConcept else None if baseXsdAttrType is None: attrObject = modelXbrl.qnameAttributes.get(qn) if attrObject: baseXsdAttrType = attrObject.baseXsdType elif attr.localName == "dimension" and elt.namespaceURI == XbrlConst.xbrldi: baseXsdAttrType = "QName" validateNode(modelXbrl, elt, attr, baseXsdAttrType, attr.value) if recurse: for child in elt.childNodes: if child.nodeType == 1: validate(modelXbrl, child)
def schemaDescendant(element, descendantNamespaceURI, descendantLocalName, name): for child in element.iterdescendants(tag="{{{0}}}{1}".format(descendantNamespaceURI,descendantLocalName)): if isinstance(child,ModelObject): # need to honor attribute/element form default if descendantLocalName == "attribute": if child.get("name") == (name.localName if isinstance(name,QName) else name): return child else: if qname(child, child.get("name")) == name: return child return None
def schemaDescendant(element, descendantNamespaceURI, descendantLocalName, name): from arelle.ModelValue import (qname,QName) for child in element.getElementsByTagNameNS(descendantNamespaceURI, descendantLocalName): # need to honor attribute/element form default if descendantLocalName == "attribute": if child.getAttribute("name") == (name.localName if isinstance(name,QName) else name): return child else: if qname(child, child.getAttribute("name")) == name: return child return None
def prefixedNameQname(self, prefixedName): """Returns ModelValue.QName of prefixedName using this element and its ancestors' xmlns. :param prefixedName: A prefixed name string :type prefixedName: str :returns: QName -- the resolved prefixed name, or None if no prefixed name was provided """ if prefixedName: # passing None would return element qname, not prefixedName None Qname return qname(self, prefixedName) else: return None
def validate(modelXbrl, elt, recurse=True, attrQname=None): if not hasattr(elt,"xValid"): text = XmlUtil.text(elt) qnElt = qname(elt) modelConcept = modelXbrl.qnameConcepts.get(qnElt) if modelConcept: baseXsdType = modelConcept.baseXsdType if len(text) == 0 and modelConcept.default is not None: text = modelConcept.default elif qnElt == XbrlConst.qnXbrldiExplicitMember: # not in DTS baseXsdType = "QName" else: baseXsdType = None if attrQname is None: validateNode(modelXbrl, elt, elt, baseXsdType, text) # validate attributes # find missing attributes for default values for i in range(len(elt.attributes)): attr = elt.attributes.item(i) attrNsURI = attr.namespaceURI if (attr.name not in ("xmlns") and attr.prefix != "xmlns"): if attrNsURI: qn = qname(attrNsURI, attr.localName) else: qn = qname(attr.localName) if attrQname and attrQname != qn: continue baseXsdAttrType = None if modelConcept: baseXsdAttrType = modelConcept.baseXsdAttrType(qn) if modelConcept else None if baseXsdAttrType is None: attrObject = modelXbrl.qnameAttributes.get(qn) if attrObject: baseXsdAttrType = attrObject.baseXsdType elif attr.localName == "dimension" and elt.namespaceURI == XbrlConst.xbrldi: baseXsdAttrType = "QName" validateNode(modelXbrl, elt, attr, baseXsdAttrType, attr.value) if recurse: for child in elt.childNodes: if child.nodeType == 1: validate(modelXbrl, child)
def loadDeprecatedConceptDates(val, deprecatedConceptDates): for modelDocument in val.modelXbrl.urlDocs.values(): ns = modelDocument.targetNamespace abbrNs = abbreviatedWildNamespace(ns) latestTaxonomyDoc = latestTaxonomyDocs.get(abbrNs) _fileName = deprecatedConceptDatesFile(val.modelXbrl.modelManager, abbrNs, latestTaxonomyDoc) if _fileName: _file = openFileStream(val.modelXbrl.modelManager.cntlr, _fileName, 'rt', encoding='utf-8') _deprecatedConceptDates = json.load(_file) # {localName: date, ...} _file.close() for localName, date in _deprecatedConceptDates.items(): deprecatedConceptDates[qname(ns, localName)] = date
def escapedNode(elt, start, empty): s = ["<"] if not start and not empty: s.append("/") s.append(str(elt.qname)) if start or empty: for n, v in elt.items(): s.append(' {0}="{1}"'.format(qname(elt, n), v)) if not start and empty: s.append("/") s.append(">") return "".join(s)
def escapedNode(elt, start, empty): s = ['<'] if not start and not empty: s.append('/') s.append(str(elt.qname)) if start or empty: for n,v in elt.items(): s.append(' {0}="{1}"'.format(qname(elt,n),v)) if not start and empty: s.append('/') s.append('>') return ''.join(s)
def isStandardArcQname(qName): return qName in { qname("{http://www.xbrl.org/2003/linkbase}definitionArc"), qname("{http://www.xbrl.org/2003/linkbase}calculationArc"), qname("{http://www.xbrl.org/2003/linkbase}presentationArc"), qname("{http://www.xbrl.org/2003/linkbase}labelArc"), qname("{http://www.xbrl.org/2003/linkbase}referenceArc"), qname("{http://www.xbrl.org/2003/linkbase}footnoteArc")}
def traceEffectiveVariableValue(self, elt, varname): # used for tracing variable value if varname.startswith('$'): varQname = qname(elt,varname[1:]) if varQname in self.inScopeVars: varValue = self.inScopeVars[varQname] if isinstance(varValue, ModelFact): return varValue.effectiveValue else: return str(varValue) else: return varname else: # not a variable name return varname