使用SimpleXML构建XBRL,命名空间如何实现
Using SimpleXML to build XBRL, how to implement namespace
我正在使用 SimpleXML 构建 XML 以用作 XBRL。
问题:
如何使用 SimpleXML 作为基础,以正确的方式在子元素上实现命名空间?
观察:
缺少命名空间(因此没有 [xbrli:xbrl]、[se-cd-base:CompanyName]。
缺少编码字符串。
我的代码:
<?php
$test_array = [
'TheCompany' => 'CompanyName'
];
$xml = new SimpleXMLElement('<xbrli/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();
结果
<?xml version="1.0"?>
<xbrli>
<CompanyName>
TheCompany
</CompanyName>
</xbrli>
想要的结果 (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>
在 XML 文档中使用名称空间时,您需要考虑三件事:
- 命名空间 URI。这是工具将识别为相同名称空间的全局唯一标识符(URI 不必指向任何地方,它只是一种组织方式 "owns" 标识符)。
- 本地前缀。这是一个任意字符串,一个特定的文档,甚至是文档的一部分,与特定的命名空间 URI 相关联,基本上只是为了让事情更紧凑。这是
<xbrli:xbrl>
等标签中 :
之前的部分。对于没有前缀的元素,文档的每个部分还有一个默认命名空间。
- 该命名空间中的元素或属性名称。这是像
<xbrli:xbrl>
. 这样的标签中 :
之后的部分
我提到所有这些是为了理解为什么您提供的示例 XML 无效,因为看起来您想要使用四个命名空间:
- 命名空间
http://www.xbrl.org/2003/linkbase
,你已经给了本地前缀link
- 一个未知的命名空间,您已为其指定了本地前缀
xbrli
;我将其命名为 http://example.org/xbrli
- 一个未知的命名空间,您已为其指定了本地前缀
se-cd-base
;我将其命名为 http://example.org/se-cd-base
- 一个未知的命名空间,您已为其指定了本地前缀
xlink
;我将其称为 http://example.org/xlink
(除非这是一个打字错误,应该是对 http://www.xbrl.org/2003/linkbase
的另一个引用?)
现在让我们尝试使用 SimpleXML...
构建您的 XML 的有效版本
首先,我们需要创建根元素,它位于 http://example.org/xbrli
命名空间中; SimpleXML没有办法创建没有任何节点的文档,所以我们必须手写第一个节点并解析它:
// 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"/>');
接下来,我们想要 http://www.xbrl.org/2003/linkbase
命名空间中的子元素 schemaRef
。我们通过 passing the namespace as the third parameter to addChild
来做到这一点,如果我们想要一个,则在元素名称中包括前缀:
// 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');
接下来,我们要在 http://example.org/xlink
命名空间中添加属性。 arguments to addAttribute
和上面类似,但是前缀是必须的:
$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');
现在对 CompanyName
元素重复;请注意 unprefixed attributes have a rather odd definition in the namespaces spec 但我们会按照您的示例保留它:
$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');
现在把它们放在一起,然后用 echo $xml->asXML();
检查,我们得到这样的结果(手动添加空格):
<?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>
或使用默认命名空间而不是前缀的等效文档:
<?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>
我正在使用 SimpleXML 构建 XML 以用作 XBRL。
问题:
如何使用 SimpleXML 作为基础,以正确的方式在子元素上实现命名空间?
观察:
缺少命名空间(因此没有 [xbrli:xbrl]、[se-cd-base:CompanyName]。
缺少编码字符串。
我的代码:
<?php
$test_array = [
'TheCompany' => 'CompanyName'
];
$xml = new SimpleXMLElement('<xbrli/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();
结果
<?xml version="1.0"?>
<xbrli>
<CompanyName>
TheCompany
</CompanyName>
</xbrli>
想要的结果 (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>
在 XML 文档中使用名称空间时,您需要考虑三件事:
- 命名空间 URI。这是工具将识别为相同名称空间的全局唯一标识符(URI 不必指向任何地方,它只是一种组织方式 "owns" 标识符)。
- 本地前缀。这是一个任意字符串,一个特定的文档,甚至是文档的一部分,与特定的命名空间 URI 相关联,基本上只是为了让事情更紧凑。这是
<xbrli:xbrl>
等标签中:
之前的部分。对于没有前缀的元素,文档的每个部分还有一个默认命名空间。 - 该命名空间中的元素或属性名称。这是像
<xbrli:xbrl>
. 这样的标签中
:
之后的部分
我提到所有这些是为了理解为什么您提供的示例 XML 无效,因为看起来您想要使用四个命名空间:
- 命名空间
http://www.xbrl.org/2003/linkbase
,你已经给了本地前缀link
- 一个未知的命名空间,您已为其指定了本地前缀
xbrli
;我将其命名为http://example.org/xbrli
- 一个未知的命名空间,您已为其指定了本地前缀
se-cd-base
;我将其命名为http://example.org/se-cd-base
- 一个未知的命名空间,您已为其指定了本地前缀
xlink
;我将其称为http://example.org/xlink
(除非这是一个打字错误,应该是对http://www.xbrl.org/2003/linkbase
的另一个引用?)
现在让我们尝试使用 SimpleXML...
构建您的 XML 的有效版本首先,我们需要创建根元素,它位于 http://example.org/xbrli
命名空间中; SimpleXML没有办法创建没有任何节点的文档,所以我们必须手写第一个节点并解析它:
// 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"/>');
接下来,我们想要 http://www.xbrl.org/2003/linkbase
命名空间中的子元素 schemaRef
。我们通过 passing the namespace as the third parameter to addChild
来做到这一点,如果我们想要一个,则在元素名称中包括前缀:
// 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');
接下来,我们要在 http://example.org/xlink
命名空间中添加属性。 arguments to addAttribute
和上面类似,但是前缀是必须的:
$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');
现在对 CompanyName
元素重复;请注意 unprefixed attributes have a rather odd definition in the namespaces spec 但我们会按照您的示例保留它:
$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');
现在把它们放在一起,然后用 echo $xml->asXML();
检查,我们得到这样的结果(手动添加空格):
<?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>
或使用默认命名空间而不是前缀的等效文档:
<?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>