Php在foreach中创建Dynamic Xml

时间:2016-05-13 08:09:48

标签: php xml oop foreach

我构建了一个基本的xml类(使用简单的xml),到目前为止我构建了简单的xml节点。

现在我想创建一个函数,在foreach中生成特定数量的节点,我在参数中指定。

现在看起来像这样:

class Xml
{

    private $data = "";

    protected $xml = "";
    protected $xmlManager = "";
    protected $menus = "";
    protected $xmlMenus = "";

    public function __construct($data = [])
    {
        $this->data = $data;
        $this->xml  = new \SimpleXmlElement('<test></test>');
        $this->setMenus();
        return $this->xml;
    }
    private function setMenus()
    {
        $this->xmlMenus = $this->xmlManager->addChild('menus');
    }

    public function setMenuNode($parameter)
    {
        $this->data->menu = []
        foreach ($this->data->menus as $menuKey => $menuValue)
        {
            $this->xmlMenu = $this->xmlMenus->addChild('menu');
            $menueValue->addAttribute($param1, $param2, $param3);
            $menueValue->addAttribute($param1, $param2, $param3);
        }

    }

}

后来我想这样称呼它

Xml->setMenuNode($param1, $param2, $param3);

哪个应创建3个菜单节点。

我的xml稍后应该如下所示。

<?xml version="1.0"?>
    <menus>
      <menu id="1" entry="title">
        ...
      </menu>
      <menu id="2" entry="title2">
        ...
      </menu>
      <menu id="3" entry="title2">
        ...
      </menu>
    </menus>
</dvd>

我不确定如何以一种好的方式管理这个。

2 个答案:

答案 0 :(得分:0)

根据您所描述的内容(PHP 5.6):

$ anaconda search -t conda bs4
Traceback (most recent call last):
  File "/usr/local/anaconda2/bin/anaconda", line 6, in <module>
    sys.exit(main())
  File "/usr/local/anaconda2/lib/python2.7/site-packages/binstar_client/scripts/cli.py", line 94, in main
    description=__doc__, version=version)
  File "/usr/local/anaconda2/lib/python2.7/site-packages/binstar_client/scripts/cli.py", line 60, in binstar_main
    add_subparser_modules(parser, sub_command_module)
  File "/usr/local/anaconda2/lib/python2.7/site-packages/clyent/__init__.py", line 115, in add_subparser_modules
    for command_module in get_sub_commands(module):
  File "/usr/local/anaconda2/lib/python2.7/site-packages/clyent/__init__.py", line 105, in get_sub_commands
    this_module = __import__(module.__package__ or module.__name__, fromlist=names)
  File "/usr/local/anaconda2/lib/python2.7/site-packages/binstar_client/commands/download.py", line 13, in <module>
    from binstar_client.utils import get_server_api
ImportError: cannot import name get_server_api

答案 1 :(得分:0)

这是两个工作,所以你应该将它分成两个类。对于松散的依赖项定义接口。菜单和项目需要附加到其父级。

我使用DOM,因为SimpleXMLElement不支持空XML文档。此解决方案也适用于SimpleXML。但只有一个额外的外部XML元素节点。

接口

这是合约,所以你应该为它定义一个接口。

interface DOMAppendable {
  public function appendTo(\DOMNode $parent);
}

项目类

对于单个项目实现界面:

class MenuItem implements DOMAppendable {

  private $_id = '';
  private $_title = '';

  public function __construct($id, $title) {
    $this->_id = $id;
    $this->_title = $title;
  }

  public function appendTo(\DOMNode $parent) {
    $document = $parent->ownerDocument ?: $parent;
    $item = $parent->appendChild($document->createElement('menu'));
    $item->setAttribute('id', $this->_id);
    $item->setAttribute('title', $this->_title);
  }
}

构造函数将数据存储到私有属性中。接口中的方法将节点附加到提供的父节点。菜单项包含更多数据,包含子项。只要他们实现了界面,它仍然可以工作。

菜单/列表类

菜单本身的类将添加的菜单项存储到数组属性中。它也实现了接口。 (因此它可以附加到另一个菜单)。实现__toString()允许将菜单转换为字符串。

class Menu implements DOMAppendable {

  private $_items = [];

  public function add(\DOMAppendable $item) {
    foreach (func_get_args() as $item) {
      if (!($item instanceOf DOMAppendable)) {
        throw new \InvalidArgumentException("Invalid menu item.");
      }
      $this->_items[] = $item;   
    }
  }

  public function appendTo(\DOMNode $parent) {
    $document = $parent->ownerDocument ?: $parent;
    $menu = $parent->appendChild($document->createElement('menus'));
    foreach ($this->_items as $item) {
      $item->appendTo($menu);
    }
  }

  public function __toString() {
    $document = new \DOMDocument();
    $document->formatOutput = TRUE;
    $this->appendTo($document);
    return $document->saveXml();
  }
}

使用

使用它可以使用新类创建菜单。

$menu = new Menu();
$menu->add(
  new MenuItem(1, 'title1'),
  new MenuItem(2, 'title2'),
  new MenuItem(3, 'title3')
);

echo $menu;

输出:

<?xml version="1.0"?>
<menus>
  <menu id="1" title="title1"/>
  <menu id="2" title="title2"/>
  <menu id="3" title="title3"/>
</menus>

界面允许使用不同的菜单项类,甚至菜单也可以是项目:

$menu = new Menu();
$menu->add(
  new MenuItem(1, 'title1'),
  new MenuItem(2, 'title2')
);
$subMenu = new Menu();
$subMenu->add(new MenuItem(3.1, 'title3.1'));
$menu->add($subMenu);

echo $menu;

输出:

<?xml version="1.0"?>
<menus>
  <menu id="1" title="title1"/>
  <menu id="2" title="title2"/>
  <menus>
    <menu id="3.1" title="title3.1"/>
  </menus>
</menus>

PHP&gt; = 5.6

PHP 5.6及更高版本支持新的variadics语法。这样可以删除func_get_args()调用并简化Menu::add()方法。

class Menu implements DOMAppendable {

  private $_items = [];

  public function add(\DOMAppendable ...$items) {
    foreach ($items as $item) {
      $this->_items[] = $item;   
    }
  }
  ...