读取和写入关联数组到XML文件

时间:2018-05-03 20:02:08

标签: php xml

我正在尝试将数组$item添加到XML文件中,以便以后能够读取所有项目。

我有以下PHP来执行此操作:

<?php
$item = array();
$item['rating'] = $_GET['rating'];
$item['comment'] = $_GET['comment'];
$item['item_id'] = $_GET['item_id'];
$item['status'] = "pending";

//Defining $xml
$xml = new SimpleXMLElement('<root/>');
array_walk_recursive($item, array($xml, 'addChild'));
$xml = $xml->asXML();

$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->loadXML($xml);

//Save XML as a file
$dom->save('reviews.xml');

然而,当我在我的XML文件中运行我得到的内容时:

  

&LT; ?xml version =“1.0”?&gt;

基本上我的阵列无处可见。 $ item的var_dump给出了

  

array(4){[“rating”] =&gt; string(1)“8”[“comment”] =&gt; string(17)“我真的很喜欢!” [ “ITEM_ID”] =&GT; string(1)“9”[“status”] =&gt; string(7)“pending”}

我怎样才能修改我的代码,以便在文件reviews.xml中保存一个数组(如果还有很多则保存它们)?

另外,我怎么能这样做,以便以后我能够访问数据;例如,将状态从待定更改为已批准?

修改

使用以下代码,我可以将项目保存到文件中:

$item = array();
$item[$_GET['rating']] = 'rating';
$item[$_GET['comment']] = 'comment';
$item[$_GET['item_id']] = 'item_id';
$item['pending'] = 'status';

$xml = new SimpleXMLElement('<root/>');
array_walk_recursive($item, array($xml, 'addChild'));


$xml->asXML('reviews.xml');

但是我仍然无法将新数据附加到根目录而不是覆盖当前保存的数据。

2 个答案:

答案 0 :(得分:1)

正如我在评论中所说的那样......您提供的代码错误WARNING DOMDocument::loadXML(): Empty string supplied as input。您从未向$xml&#39; ...

分配任何内容

正确的错误报告/记录有助于发现这些错误。

<?php
$item = array();
$item['rating'] = 'a';
$item['comment'] = 'b';
$item['item_id'] = 'c';
$item['status'] = "pending";

//Defining $xml
$xml = new SimpleXMLElement('<root/>');
array_walk_recursive($item, array($xml, 'addChild'));

//THIS IS THE LINE YOU WERE MISSING
$xml = $xml->asXML();

$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->loadXML($xml);

//Save XML as a file
$dom->save('reviews.xml');

如果你回应它......

var_dump($dom->saveHTML()); 


> string(80)
> "<root><a>rating</a><b>comment</b><c>item_id</c><pending>status</pending></root>"

请避免使用其他问题更新现有问题。

数据库可以使任务更容易。使用平面文件可以很好地工作,XML或其他格式。您需要能够通过item_id检索记录,然后修改它,然后替换它。这就是它的要点。

答案 1 :(得分:1)

所以这里是对您的代码进行彻底检查,根据您的各种评论和更新,对您的方法和XML方案进行一些更改。

首先,不要创建看起来像这样的XML:

<root>
    <rating>a</rating>
    <comment>b</comment>
    <item_id>c</item_id>
    <status>pending</status>
</root>

您将以这样的方式存储XML:

<root>
    <item id="c">
        <rating>a</rating>
        <comment>b</comment>
        <status>pending</status>
    </item>
</root>

这是基于您的一些评论:

  1. 您希望添加到XML文件而不是覆盖现有文件内容。这表明您要存储多个项目。这也可以解释为什么你有一个属性item_id。所以,而不是像一堆乱七八糟的XML:

    <root>
        <rating>a</rating>
        <comment>b</comment>
        <item_id>c</item_id>
        <status>pending</status>
        <rating>d</rating>
        <comment>e</comment>
        <item_id>f</item_id>
        <status>pending</status>
        <rating>g</rating>
        <comment>h</comment>
        <item_id>i</item_id>
        <status>pending</status>
    </root>
    
  2. 在哪里无法知道哪个项目是哪个,您将每个项目属性集存储在<item>元素上。由于您希望根据其item_id轻松抓取某个项目以更新该项目,因此item_id使<item>的属性更有意义,而不是让它成为<item>

    1. 您希望能够更新状态。这就是item_id上存储item的地方派上用场了。如果有人使用现有item_id提交请求,您可以更新该项,包括其status元素。或者你可以在需要的时候从其他过程中完成它等等。
    2. 这是我为此鼓起的代码。请注意,它当前未设置为查找具有该项ID的现有元素,但应该可以使用现有的SimpleXML函数/方法。

      $item = array();
      
      $item_id = "c";
      $item['rating'] = 'a';
      $item['comment'] = 'b';
      $item['status']  = "pending";
      
      $xml = simplexml_load_file('ratings.xml');
      
      //if ratings.xml not found or not valid xml, create clean XML with <root/>
      if($xml === false) {
          $xml = new SimpleXMLElement('<root/>');
      }
      
      $xml_item = $xml->addChild("item");
      
      $xml_item->addAttribute("id", $item_id);
      
      foreach($item as $name => $value) {
          $xml_item->addChild($name, $value);
      }
      
      $xml->asXML('ratings.xml');
      

      请注意,我对您现有代码所做的一项重大更改正在从使用array_walk_recursive更改为简单foreacharray_walk_recursive为此目的是一个捷径,导致比它解决的更多问题。例如,您必须在$item数组上交换密钥和值,这会令人困惑。由于您没有多维数组,因此您目前所做的事情也没有必要。即使你这样做,array_walk_recursive也不是递归处理数组循环的正确选择,因为它会将每个数组成员添加到XML的根目录,而不是将子数组作为其父项的子项添加为它们出现在实际的数组中。重点是,它令人困惑,它不会增加任何价值,使用foreach可以更明确地了解你的实际行动。

      我也改变了

      $item['item_id'] = 'c';
      

      $item_id = 'c';
      

      然后将其作为属性添加到item元素中:

      $xml_item->addAttribute("id", $item_id);
      

      这与我之前概述的新架构一致。

      最后,我不是将XML传递给DOMDocument,而是使用

      $xml->asXML('ratings.xml');
      

      SimpleXML已经删除了任何额外的空格,因此无需使用DOMDocument来实现此目的。

      基于原始代码中的一些违反直觉的部分,看起来您可能已经完成了大量的复制和粘贴以实现它。这是我们大多数人开始的地方,但是对于诸如“我完全不了解这段代码正在做什么之类的东西,我只是从一个能够完成我需要的东西的脚本中抓取它”这个问题是一个好主意。如果我们不假设您正在使用您拥有的代码,因为您需要或者这是一个有意识的决定等,并且我们必须在该代码的约束下工作,它将为我们节省大量的时间和悲伤。

      我希望这能让你有一个良好的开端。

      更新

      我正在搞乱它,并且如果<item>设置为id的项已经存在,则会更新现有的$item_id。它有点笨重,但经过测试并且有效。

      这假定$item_id$item数组正常设置,以及检索现有XML,如上所述。我在变更之前提供了参考线:

      $xml = simplexml_load_file('ratings.xml');
      
      //if ratings.xml not found or not valid xml, create clean XML with <root/>
      if($xml === false) {
          $xml = new SimpleXMLElement('<root/>');
      }
      //query with xpath for existing item with $item_id
      $item_with_id = $xml->xpath("/root/item[@id='{$item_id}']");
      
      // if the xpath returns a result, update that item with new values.
      
      if(count($item_with_id) > 0) {
          $xml_item = $item_with_id[0];
      
          foreach($item as $name => $value) {
              $xml_item->$name = $value;
          }
      } else {
      // if the xpath returns no results, create new item element.    
          $xml_item = $xml->addChild("item");
      
          $xml_item->addAttribute("id", $item_id);
      
          foreach($item as $name => $value) {
              $xml_item->addChild($name, $value);
          }
      }