【问题标题】:Using SimpleXML to build XBRL, how to implement namespace使用 SimpleXML 构建 XBRL,如何实现命名空间
【发布时间】:2020-05-22 09:11:53
【问题描述】:

我正在使用 SimpleXML 构造要用作 XBRL 的 XML。

问题:

如何以正确的方式在子元素上实现命名空间,使用 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。没有xbrli 或se-cd-base 命名空间的定义。不过,SimpleXMLElement constructor 具有可用于设置命名空间的 $ns 和 $is_prefix 参数。
  • @Furgas 更新了想要的结果是(XBRL)的问题。
  • 实际上,$ns 和 $is_prefix 的工作方式与我想象的不同(这就是为什么我更喜欢使用 DOM 而不是 SimpleXML)。请参阅此answer 以获取线索。

标签: php arrays simplexml php-7.3


【解决方案1】:

在 XML 文档中使用命名空间时,需要考虑三件事:

  • 命名空间 URI。这是工具将识别为同一个命名空间的全局唯一标识符(URI 不必指向任何地方,它只是一种组织“拥有”标识符的人的方式)。
  • 本地前缀。这是一个任意字符串,一个特定的文档,甚至是文档的一部分,与一个特定的命名空间 URI 相关联,基本上只是为了让事情更紧凑。这是: 之前的部分,例如&lt;xbrli:xbrl&gt;。对于没有前缀的元素,文档的每个部分还有一个默认命名空间。
  • 该命名空间中的元素或属性名称。这是: 之后的部分,例如&lt;xbrli:xbrl&gt;。

我提到这一切是为了理解为什么您提供的示例 XML 无效,因为看起来您想使用四个命名空间:

  1. 命名空间http://www.xbrl.org/2003/linkbase,您为其指定了本地前缀link
  2. 一个未知的命名空间,你给它的本地前缀xbrli;我会打电话给这个http://example.org/xbrli
  3. 一个未知的命名空间,你给它的本地前缀se-cd-base;我会打电话给这个http://example.org/se-cd-base
  4. 一个未知的命名空间,你已经给了本地前缀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-&gt;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>

【讨论】:

  • 实际上已移至 DOMDocument。更多代码行但更好的灵活性和概述。
猜你喜欢
  • 1970-01-01
  • 2012-01-06
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
  • 2020-04-19
  • 2013-04-30
  • 2011-01-02
相关资源
最近更新 更多