0

我正在尝试使用 Yii2 构建 XML 响应。但我对 itemtag有一些问题

Itemtag 命名数组中表示数字键的元素。例子

$itemTag = 'test';

return $response = ['tests' => [0 => 'a', 1 => 'b']];

XML 结果

<response>
   <tests>
      <test>a</test>
      <test>b</test>
   </tests>
</response>

但是当我想在测试中创建一个新组时,它仍然会得到 itemtag 名称。例子

return $response = ['tests' => [0 => 'a', 1 => 'b', 'days' => [0 => 'd1', 1 => 'd2']]];

这是 xml 结果

<response>
  <tests>
    <test>a</test>
    <test>b</test>
    <days>
      <test>d1</test> // this should be day
      <test>d2</test> // this should be day
    </days>
  </tests>
</response>

我该如何解决这个问题?

4

1 回答 1

0

让您自定义 XmlResponseFormatter 并覆盖此函数:

protected function buildXml($element, $data)
{
    if (is_array($data)
        || ($data instanceof \Traversable
        && $this->useTraversableAsArray
        && !$data instanceof Arrayable)
    ) {

        foreach ($data as $name => $value) {

            if(is_array($value) && $this->checkArrayKeyNumber($value)){
                foreach ($value as $number => $childValue) {
                    $ele = new DOMElement($name);
                    $element->insertBefore(
                        $element->ownerDocument->createTextNode("\n")
                    );
                    $element->appendChild($ele);
                    $this->buildXml($ele, $childValue);
                }
                continue;
            }

            if (is_int($name) && is_object($value)) {
                $this->buildXml($element, $value);
            } elseif (is_array($value) || is_object($value)) {
                $child = new DOMElement($this->getValidXmlElementName($name));
                $element->insertBefore(
                    $element->ownerDocument->createTextNode("\n")
                );
                $element->appendChild($child);
                $this->buildXml($child, $value);
            } else {
                $child = new DOMElement($this->getValidXmlElementName($name));
                $element->insertBefore(
                    $element->ownerDocument->createTextNode("\n")
                );
                $element->appendChild($child);
                $child->appendChild(
                    new DOMText($this->formatScalarValue($value))
                );
            }
        }

    } elseif (is_object($data)) {
        if ($this->useObjectTags) {
            $child = new DOMElement(StringHelper::basename(get_class($data)));
            $element->appendChild($child);
        } else {
            $child = $element;
        }
        if ($data instanceof Arrayable) {
            $this->buildXml($child, $data->toArray());
        } else {
            $array = [];
            foreach ($data as $name => $value) {
                $array[$name] = $value;
            }
            $this->buildXml($child, $array);
        }
    } else {
        $element->appendChild(new DOMText($this->formatScalarValue($data)));
    }
    $element->insertBefore(
        $element->ownerDocument->createTextNode("\n")
    );
}

添加新函数以检查您的数组数据的键是数字的位置,例如

[
    'days' =>
    [
        0  => 'd1',
        1  => 'd2'
    ]
]

这个函数

private function checkArrayKeyNumber($array)
{
    $keys = array_keys($array);
    $numeric = true;
    foreach ($keys as $key) {
        if(!is_numeric($key)){
            $numeric = false;
        }
    }

    return $numeric;
}

最后,添加到您的自定义响应类 init()

    public function init()
{
    parent::init();
    $this->formatters['xml']
        = 'path\to\your\custom\XmlResponseFormatter';
}
于 2018-04-10T06:16:46.773 回答