I am using SimpleXML to construct XML to be used as XBRL.
Question:
How can I implement namespace on child element the correct way, using SimpleXML as base?
Observations:
Missing namespace (thus there are no [xbrli:xbrl], [se-cd-base:CompanyName].
Missing encoding string.
My code:
<?php
$test_array = [
'TheCompany' => 'CompanyName'
];
$xml = new SimpleXMLElement('<xbrli/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();
Result
<?xml version="1.0"?>
<xbrli>
<CompanyName>
TheCompany
</CompanyName>
</xbrli>
Wanted result (XBRL)
<?xml version="1.0" encoding="UTF-8"?>
<xbrli:xbrl xmlns:link = "http://www.xbrl.org/2003/linkbase">
<link:schemaRef
xlink:type="simple"
xlink:href="http://xbrl.taxonomier.se/se/fr/gaap/k2/risbs/2017-09-30/se-k2-risbs-2017-09-30.xsd"/
>
<se-cd-base:CompanyName
contextRef="period0">
TheCompany
</se-cd-base:CompanyName>
</xbrli:xbrl>
When using namespaces in an XML document, you need to think about three things:
:
in a tag like <xbrli:xbrl>
. There is also a default namespace for each part of a document, for elements with no prefix.:
in a tag like <xbrli:xbrl>
.I mention all this to understand why the sample XML you provide is invalid, because it looks like you want to use four namespaces:
http://www.xbrl.org/2003/linkbase
which you have given the local prefix link
xbrli
; I'll call this one http://example.org/xbrli
se-cd-base
; I'll call this one http://example.org/se-cd-base
xlink
; I'll call this one http://example.org/xlink
(unless this was a typo and should have been another reference to http://www.xbrl.org/2003/linkbase
?)Now let's try to construct a valid version of your XML using SimpleXML...
First, we need to create the root element, which is in the http://example.org/xbrli
namespace; SimpleXML doesn't have a way to create a document without any nodes, so we have to write the first node by hand and parse it:
// Using xbrli as prefix for http://example.org/xbrli
$xml = new SimpleXMLElement('<xbrli xmlns="http://example.org/xbrli"/>');
// Or using http://example.org/xbrli as the default namespace for the document
$xml = new SimpleXMLElement('<xbrli xmlns="http://example.org/xbrli"/>');
Next, we want a child element schemaRef
in the http://www.xbrl.org/2003/linkbase
namespace. We do this by passing the namespace as the third parameter to addChild
, and including the prefix in the element name if we want one:
// Using link as the prefix for http://www.xbrl.org/2003/linkbase
$schemaRef = $xml->addChild('link:schemaRef', null, 'http://www.xbrl.org/2003/linkbase');
// Or making http://www.xbrl.org/2003/linkbase the default namespace for this section
$schemaRef = $xml->addChild('schemaRef', null, 'http://www.xbrl.org/2003/linkbase');
Next, we want to add attributes in the http://example.org/xlink
namespace. The arguments to addAttribute
are similar to the above, but the prefix is mandatory:
$schemaRef->addAttribute('xlink:type', 'simple', 'http://example.org/xlink');
$schemaRef->addAttribute('xlink:href', 'http://xbrl.taxonomier.se/se/fr/gaap/k2/risbs/2017-09-30/se-k2-risbs-2017-09-30.xsd', 'http://example.org/xlink');
Now repeat for the CompanyName
element; note that unprefixed attributes have a rather odd definition in the namespaces spec but we'll keep it as per your example:
$CompanyName = $xml->addChild('se-cd-base:CompanyName', 'The Company', 'http://example.org/se-cd-base');
// Again, we can declare a default namespace rather than a prefix:
$CompanyName = $xml->addChild('CompanyName', 'The Company', 'http://example.org/se-cd-base');
// Attribute with no namespace
$CompanyName->addAttribute('contextRef', 'period0');
Now put it all together, and check with echo $xml->asXML();
and we get something like this (whitespace added manually):
<?xml version="1.0"?>
<xbrli xmlns="http://example.org/xbrli">
<link:schemaRef
xmlns:link="http://www.xbrl.org/2003/linkbase"
xmlns:xlink="http://example.org/xlink"
xlink:type="simple"
xlink:href="http://xbrl.taxonomier.se/se/fr/gaap/k2/risbs/2017-09-30/se-k2-risbs-2017-09-30.xsd"
/>
<se-cd-base:CompanyName
xmlns:se-cd-base="http://example.org/se-cd-base"
contextRef="period0"
>The Company
</se-cd-base:CompanyName>
</xbrli>
Or an equivalent document using default namespaces rather than prefixes:
<?xml version="1.0"?>
<xbrli xmlns="http://example.org/xbrli">
<schemaRef
xmlns="http://www.xbrl.org/2003/linkbase"
xmlns:xlink="http://example.org/xlink"
xlink:type="simple"
xlink:href="http://xbrl.taxonomier.se/se/fr/gaap/k2/risbs/2017-09-30/se-k2-risbs-2017-09-30.xsd"
/>
<CompanyName
xmlns="http://example.org/se-cd-base"
contextRef="period0"
>
The Company
</CompanyName>
</xbrli>