【问题标题】:Php create Dynamic Xml in foreachphp在foreach中创建动态Xml
【发布时间】:2016-05-13 08:09:48
【问题描述】:

我构建了一个基本的 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>

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

【问题讨论】:

  • 你不能从构造函数返回值。
  • 你到底是什么意思
  • 在删除构造函数之前,您在其中调用了 return $this-&gt;xml;。那是行不通的。现在没有构造函数,你的属性都是空字符串,但用作对象。
  • 我正在构建一个 Xml 对象并像这样调用它echo "&lt;pre&gt;".print_r($xml,true)."&lt;/pre&gt;"; 只是为了查看结果,但是你知道如何解决我的问题吗:)

标签: php xml oop foreach


【解决方案1】:

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

我使用 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 >= 5.6

PHP 5.6 及更高版本支持新的可变参数语法。这允许删除func_get_args() 调用并简化Menu::add() 方法。

class Menu implements DOMAppendable {

  private $_items = [];

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

【讨论】:

    【解决方案2】:

    根据您的描述,您会得到(PHP 5.6):

    function setMenuNode(...$parameters)
    {
      foreach ($parameters as $parameter) {
        $this->xmlMenu = $this->xmlMenus->addChild('menu');
        $menueValue->addAttribute('id', $parameter);
        $menueValue->addAttribute('entry', 'title' . $parameter);
      }
    }
    

    【讨论】:

    • 谢谢,但我还需要使标题名称动态化,您将如何管理?
    • 取决于您在参数中设置的内容。
    • 祝你好运,使用 splat 运算符($parameters 前的三个点)您可以将动态数量的参数传递给您的函数:Xml->setMenuNode($param1, $param2, $param3, $param4等);
    • 太糟糕了,我坐在 5.5 上 :) 还是谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 2021-09-05
    相关资源
    最近更新 更多