def test_xml_namespace(self): from lxml.builder import ElementMaker maker = ElementMaker(namespace='http://foo/', nsmap=self.nsmap) self.assertEqual(maker._namespace, '{http://foo/}') with xml_namespace(maker, 'bar'): self.assertEqual(maker._namespace, '{http://bar/}') self.assertEqual(maker._namespace, '{http://foo/}')
def chart_serializer(chart, filing, maker): with xml_namespace(maker, None, auto_convert=True) as maker: role = convert_role_url(chart.role, filing) link = maker.presentationLink(**{ 'xlink:type': 'extended', 'xlink:role': role, }) link.append(make_loc(chart.loc_fact, maker)) for order, (n_parent, n_child) in enumerate(chart.walk_tree()): if n_parent is None: n_parent = (chart.loc_fact, None) n_child, n_parent = n_child[0], n_parent[0] link.append(make_loc(n_child, maker)) link.append(make_presentationArc(n_child, n_parent, order, maker)) return link # Facts should be able to create their own locs # presentationArcs are derived from data in the chart #<loc # xlink:type="locator" # xlink:href="http://taxonomies.xbrl.us/us-gaap/2009/non-gaap/dei-2009-01-31.xsd#dei_DocumentPeriodEndDate" # xlink:label="DocumentPeriodEndDate" # xlink:title="DocumentPeriodEndDate" #/> # Presentationarcs go from label to label
def test_xml_namespace(self): from lxml.builder import ElementMaker maker = ElementMaker(namespace='http://foo/', nsmap =self.nsmap) self.assertEqual(maker._namespace, '{http://foo/}') with xml_namespace(maker, 'bar'): self.assertEqual(maker._namespace, '{http://bar/}') self.assertEqual(maker._namespace, '{http://foo/}')
def presentation_serializer(serializer): filing = serializer.filing date = filing.date company = filing.company nsmap = gen_nsmap(filing, 'Presentation') maker = ElementMaker(nsmap=nsmap) with xml_namespace(maker, None, auto_convert=True) as maker: linkbase = maker.linkbase( **{ #find out about this 'xsi:schemaLocation': 'http://www.xbrl.org/2003/linkbase http://www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd', 'xmlns': 'http://www.xbrl.org/2003/linkbase', }) for chart in filing.charts: roleRef = maker.roleRef( **{ 'roleURI': convert_role_url(chart.role, filing), 'xlink:type': 'simple', 'xlink:href': '{0}#{1}'.format(serializer.document_name('Schema'), chart.role) }) linkbase.append(roleRef) chart.bind(serializer) linkbase.append(chart_serializer(chart, filing, maker)) return linkbase
def presentation_serializer(serializer): filing = serializer.filing date = filing.date company = filing.company nsmap = gen_nsmap(filing, 'Presentation') maker = ElementMaker(nsmap=nsmap) with xml_namespace(maker, None, auto_convert=True) as maker: linkbase = maker.linkbase(**{ #find out about this 'xsi:schemaLocation': 'http://www.xbrl.org/2003/linkbase http://www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd', 'xmlns': 'http://www.xbrl.org/2003/linkbase', }) for chart in filing.charts: roleRef = maker.roleRef(**{ 'roleURI': convert_role_url(chart.role, filing), 'xlink:type': 'simple', 'xlink:href': '{0}#{1}'.format( serializer.document_name('Schema'), chart.role ) }) linkbase.append(roleRef) chart.bind(serializer) linkbase.append(chart_serializer(chart, filing, maker)) return linkbase
def make_loc(fact, maker, namespace=None): with xml_namespace(maker, namespace, auto_convert=True) as maker: return maker.loc(**{ 'xlink:type': 'locator', 'xlink:href': fact.href, 'xlink:label': fact.label, 'xlink:title': fact.title, })
def test_xml_namespace_none(self): from lxml.builder import ElementMaker maker = ElementMaker(namespace='http://foo/', nsmap=self.nsmap) self.assertEqual(maker._namespace, '{http://foo/}') with xml_namespace(maker, None): self.assertEqual(etree.tostring(maker.test(), pretty_print=True), '<test xmlns:test="http://test/" xmlns:foo="http://foo/" xmlns:bar="http://bar/"/>\n') self.assertEqual(maker._namespace, '{http://foo/}')
def make_labelArc(fact, maker, utitle, namespace=None): with xml_namespace(maker, namespace, auto_convert=True) as maker: return maker.labelArc(**{ 'xlink:type': 'arc', 'xlink:arcrole': 'http://www.xbrl.org/2003/arcrole/concept-label', 'xlink:from': fact.label, 'xlink:to': utitle, 'xlink:title': 'label: {0} to label_{0}'.format(fact.label) })
def make_loc(fact, maker, namespace=None): with xml_namespace(maker, namespace, auto_convert=True) as maker: return maker.loc( **{ 'xlink:type': 'locator', 'xlink:href': fact.href, 'xlink:label': fact.label, 'xlink:title': fact.title, })
def make_label(fact, maker, utitle, namespace=None): with xml_namespace(maker, namespace, auto_convert=True) as maker: return maker.label(fact.label_text, **{ 'xlink:type': 'resource', 'xlink:label': utitle, 'xlink:role': 'http://www.xbrl.org/2003/role/label', 'xlink:title': 'label_{0}'.format(fact.title), 'xml:lang': 'en', 'id': utitle, })
def serialize(self, value, unit, context, maker): with xml_namespace(maker, self.namespace) as maker: return maker.__getattr__(self.label)('{0}'.format(value), **{ 'contextRef': context.make_id(), 'unitRef': unit.id, 'decimals': '0', })
def serialize(self, value, unit, context, maker): with xml_namespace(maker, self.namespace) as maker: return maker.__getattr__(self.label)( '{0}'.format(value), **{ 'contextRef': context.make_id(), 'unitRef': unit.id, 'decimals': '0', } )
def test_xml_namespace_none(self): from lxml.builder import ElementMaker maker = ElementMaker(namespace='http://foo/', nsmap=self.nsmap) self.assertEqual(maker._namespace, '{http://foo/}') with xml_namespace(maker, None): self.assertEqual( etree.tostring(maker.test(), pretty_print=True), '<test xmlns:test="http://test/" xmlns:foo="http://foo/" xmlns:bar="http://bar/"/>\n' ) self.assertEqual(maker._namespace, '{http://foo/}')
def make_label(fact, maker, utitle, namespace=None): with xml_namespace(maker, namespace, auto_convert=True) as maker: return maker.label( fact.label_text, **{ 'xlink:type': 'resource', 'xlink:label': utitle, 'xlink:role': 'http://www.xbrl.org/2003/role/label', 'xlink:title': 'label_{0}'.format(fact.title), 'xml:lang': 'en', 'id': utitle, })
def make_labelArc(fact, maker, utitle, namespace=None): with xml_namespace(maker, namespace, auto_convert=True) as maker: return maker.labelArc( **{ 'xlink:type': 'arc', 'xlink:arcrole': 'http://www.xbrl.org/2003/arcrole/concept-label', 'xlink:from': fact.label, 'xlink:to': utitle, 'xlink:title': 'label: {0} to label_{0}'.format(fact.label) })
def serialize(self, maker, cik): with xml_namespace(maker, 'xbrli'): return maker.context( maker.entity( maker.identifier('%010d' % int(cik), scheme="http://www.sec.gov/CIK") ), maker.period( *self.period_node(maker) ), id = self.make_id() )
def make_calculationArc(child, parent, order, weight, maker, namespace=None): with xml_namespace(maker, namespace, auto_convert=True) as maker: return maker.presentationArc(**{ 'xlink:type': 'arc', 'xlink:arcrole': 'http://www.xbrl.org/2003/arcrole/summation-item', 'xlink:from': parent.label, 'xlink:to': child.label, 'xlink:title': 'calculation: {0} to {1}'.format( parent.label, child.label ), 'order': '{0:.1f}'.format(order), 'weight': '{0:.1f}'.format(weight), })
def make_presentationArc(child, parent, order, maker, namespace=None): with xml_namespace(maker, namespace, auto_convert=True) as maker: return maker.presentationArc(**{ 'xlink:type': 'arc', 'xlink:arcrole': 'http://www.xbrl.org/2003/arcrole/parent-child', 'xlink:from': parent.label, 'xlink:to': child.label, 'xlink:title': 'presentation: {0} to {1}'.format( parent.label, child.label ), 'use': 'optional', 'order': '{0:.1f}'.format(order) })
def chart_serializer(chart, filing, maker): with xml_namespace(maker, None, auto_convert=True) as maker: role = convert_role_url(chart.role, filing) link = maker.calculationLink(**{ 'xlink:type': 'extended', 'xlink:role': role, }) for calc_fact in chart.calculation_facts: link.append(make_loc(calc_fact, maker)) for order, (fact, weight) in enumerate(calc_fact.calc_items): link.append(make_loc(fact, maker)) link.append(make_calculationArc(fact, calc_fact, order+1, weight, maker)) return link
def make_presentationArc(child, parent, order, maker, namespace=None): with xml_namespace(maker, namespace, auto_convert=True) as maker: return maker.presentationArc( **{ 'xlink:type': 'arc', 'xlink:arcrole': 'http://www.xbrl.org/2003/arcrole/parent-child', 'xlink:from': parent.label, 'xlink:to': child.label, 'xlink:title': 'presentation: {0} to {1}'.format(parent.label, child.label), 'use': 'optional', 'order': '{0:.1f}'.format(order) })
def label_serializer(serializer): filing = serializer.filing date = filing.date company = filing.company nsmap = gen_nsmap(filing, 'Label') maker = ElementMaker(nsmap=nsmap) with xml_namespace(maker, 'link', auto_convert=True) as maker: linkbase = maker.linkbase( **{ #find out about this 'xsi:schemaLocation': 'http://www.xbrl.org/2003/linkbase http://www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd' }) labellink = maker.labelLink( **{ 'xlink:type': 'extended', 'xlink:role': 'http://www.xbrl.org/2003/role/link', }) locs = set([]) for (fact, unit), context, data in filing.data_stream: if fact.href not in locs: labellink.append(make_loc(fact, maker, namespace='link')) locs.add(fact.href) facts = set([]) for (fact, unit), context, data in filing.data_stream: if (fact, unit) in facts: continue facts.add((fact, unit)) utitle = 'label_{0}_{1}'.format(fact.title, uid()) labellink.append(make_label(fact, maker, utitle, namespace='link')) labellink.append( make_labelArc(fact, maker, utitle, namespace='link')) linkbase.append(labellink) return linkbase
def instance_serializer(serializer): #looks like #<xbrli:xbrl [namespaces]> #<link:schemaRef to xsd document> #[<contexts>] #[<units>] #[<facts>] #</xbrli:xbrl> filing = serializer.filing date = filing.date company = filing.company nsmap = gen_nsmap(filing, 'Instance') maker = ElementMaker(namespace=nsmap['xbrli'], nsmap=nsmap) xbrl = maker.xbrl() with xml_namespace(maker, 'link'): schemaRef = maker.schemaRef(**convert_attribs( { 'xlink:type': 'simple', 'xlink:href': serializer.document_name('Schema'), }, nsmap)) xbrl.append(schemaRef) #Loop over contexts, appending to xbrl for context in set(filing.contexts): xbrl.append(context.serialize(maker, company.cik)) #Loop over units, appending to xbrl for unit in set(filing.units): xbrl.append(unit.serialize(maker)) #Loop over facts appending to xbrl for (fact, unit), context, value in filing.data_stream: xbrl.append(fact.serialize(value, unit, context, maker)) return xbrl
def instance_serializer(serializer): #looks like #<xbrli:xbrl [namespaces]> #<link:schemaRef to xsd document> #[<contexts>] #[<units>] #[<facts>] #</xbrli:xbrl> filing = serializer.filing date = filing.date company = filing.company nsmap = gen_nsmap(filing, 'Instance') maker = ElementMaker(namespace=nsmap['xbrli'], nsmap=nsmap) xbrl = maker.xbrl() with xml_namespace(maker, 'link'): schemaRef = maker.schemaRef(**convert_attribs({ 'xlink:type': 'simple', 'xlink:href': serializer.document_name('Schema'), }, nsmap)) xbrl.append(schemaRef) #Loop over contexts, appending to xbrl for context in set(filing.contexts): xbrl.append(context.serialize(maker, company.cik)) #Loop over units, appending to xbrl for unit in set(filing.units): xbrl.append(unit.serialize(maker)) #Loop over facts appending to xbrl for (fact, unit), context, value in filing.data_stream: xbrl.append(fact.serialize(value, unit, context, maker)) return xbrl
def label_serializer(serializer): filing = serializer.filing date = filing.date company = filing.company nsmap = gen_nsmap(filing, 'Label') maker = ElementMaker(nsmap=nsmap) with xml_namespace(maker, 'link', auto_convert=True) as maker: linkbase = maker.linkbase(**{ #find out about this 'xsi:schemaLocation': 'http://www.xbrl.org/2003/linkbase http://www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd' }) labellink = maker.labelLink(**{ 'xlink:type': 'extended', 'xlink:role': 'http://www.xbrl.org/2003/role/link', }) locs = set([]) for (fact, unit), context, data in filing.data_stream: if fact.href not in locs: labellink.append(make_loc(fact, maker, namespace='link')) locs.add(fact.href) facts = set([]) for (fact, unit), context, data in filing.data_stream: if (fact, unit) in facts: continue facts.add((fact, unit)) utitle = 'label_{0}_{1}'.format(fact.title, uid()) labellink.append(make_label(fact, maker, utitle, namespace='link')) labellink.append(make_labelArc(fact, maker, utitle, namespace='link')) linkbase.append(labellink) return linkbase
def period_node(self, maker): with xml_namespace(maker, 'xbrli'): if self.instant: return [maker.instant(self.date_strings)] return [maker.startDate(self.date_strings[0]), maker.endDate(self.date_strings[1])]
def serialize(self, maker): with xml_namespace(maker, 'xbrli'): return maker.unit(maker.measure(self.measure), id=self.id)
def serialize(self, maker): with xml_namespace(maker, "xbrli"): return maker.unit(maker.measure(self.measure), id=self.id)
def schema_serializer(serializer): filing = serializer.filing date = filing.date company = filing.company nsmap = gen_nsmap(filing, 'Schema') maker = ElementMaker(namespace=nsmap['xsd'], nsmap=nsmap) targetNamespace = '{0}{1}'.format(filing.company.url, filing.date) schema = maker.schema({ 'targetNamespace': targetNamespace, 'elementFormDefault': 'qualified', }) #link bases annotation = maker.annotation() appinfo = maker.appinfo() bases = serializer.determine_files() bases.remove('Instance') bases.remove('Schema') roles = { 'Presentation': "http://www.xbrl.org/2003/role/presentationLinkbaseRef", 'Calculation': "http://www.xbrl.org/2003/role/calculationLinkbaseRef", 'Label': "http://www.xbrl.org/2003/role/labelLinkbaseRef", } with xml_namespace(maker, 'link', auto_convert=True) as maker: for base in bases: appinfo.append(maker.linkbaseRef(**{ 'xlink:type': 'simple', 'xlink:href': serializer.document_name(base), 'xlink:role': roles[base], 'xlink:arcrole': "http://www.w3.org/1999/xlink/properties/linkbase", })) for i, chart in enumerate(filing.charts): roleType = maker.roleType(**{ 'roleURI': convert_role_url(chart.role, filing), 'id': chart.role }) roleType.append(maker.definition('%04d - %s' % (10*(i+1), chart.role) )) roleType.append(maker.usedOn('link:presentationLink')) appinfo.append(roleType) annotation.append(appinfo) schema.append(annotation) #imports for the facts (probably have to derive this from facts) imports = { "http://www.xbrl.org/2003/instance": "http://www.xbrl.org/2003/xbrl-instance-2003-12-31.xsd", "http://xbrl.us/us-types/2009-01-31": "http://taxonomies.xbrl.us/us-gaap/2009/elts/us-types-2009-01-31.xsd", } for namespace, schemaLocation in imports.items(): #Terrible hack to get around import being a keyword schema.append(maker.__getattr__('import')({ 'namespace': namespace, 'schemaLocation': schemaLocation, })) #Create a custom element for everything fact_table = {} for (fact, _), _, _ in filing.data_stream: fact_table[fact.label] = fact facts = fact_table.values() with xml_namespace(maker, 'xsd', auto_convert=True) as maker: #append facts for the chart abstract facts for chart in filing.charts: fact = chart.loc_fact schema.append(maker.element(**{ 'id': fact.label, 'name': fact.label, 'type': 'xbrli:stringItemType', 'substitutionGroup': 'xbrli:item', 'nillable': 'true', 'abstract': 'true', 'xbrli:periodType': 'duration', })) #append the rest of the facts we need to define for fact in facts: schema.append(maker.element(**{ 'id': fact.label, 'name': fact.label, 'nillable': 'true', 'substitutionGroup': 'xbrli:item', 'type': 'xbrli:monetaryItemType', 'xbrli:periodType': fact.period, })) return schema