根据条件使用原始文件中的 XML 数据创建新文件

问题描述 投票:0回答:1

在页面上,我让它从 XML 文件加载内容。 然后有一个表单,根据与 $_GET['cat'] 值匹配的类别名称来显示此 XML 文件中的条目。

该表格允许我编辑 2 个值(最小值和标称值)。 提交时,它将具有新值的 XML 内容保存到文件中,但是我只希望它在类别名称与 $_GET['cat'] 值匹配时保存数据。

我尝试了一些方法,但它仍然不断保存原始 XML 中的所有内容以及更新的值,而不是仅保存与类别名称匹配的数据。

这是我的代码:

if(isset($_POST))
{
    $row = array();
    $r = 0;
    $catName = str_replace('.xml','',$_POST['catFile']); // Add change
    foreach($_POST['row'] as $row)
    {
        $catFile = $_POST['catFile'];
        $ufile = simplexml_load_file('newTypes2.xml');
        foreach($ufile->type as $type)
        {
          if($type->category['name'] == $catName)
          {
            if($type['name'] == $_POST['item'][$r])
            {
                $type->nominal = $_POST['nominal'][$r];
                $type->min = $_POST['min'][$r];
                break;
            }
            file_put_contents($catFile, $ufile->asXML());
          }
        }
        $r++;
    }
}

表格如下:

if(!file_exists('newTypes2.xml'))
{
 $xml = simplexml_load_file('types.xml');   
} else {
$xml = simplexml_load_file('newTypes2.xml');
}
$json = json_encode($xml);
$array = json_decode($json,TRUE);
$cat = $_GET['cat'];

$i = 0;
$count = count($xml->type);
echo '<form class="form-horizontal" method="post" action="'.$_SERVER['PHP_SELF'].'">';
foreach($xml->type as $type)
{
    if($cat == 'weapons')
    {
        if($type->category['name'] == "weapons")
        {
        $cnt = 0;
        echo '<div class="form-group"><input type="hidden" name="row[]" value="'.$cnt.'"><input type="hidden" name="item[]" value="'.$type['name'].'">';
        echo '<div class="col-md-4"><strong>'.$type['name'].'</strong></div> <div class="col-md-4">Nominal : <input class="form-control" type="text" value="'.$type->nominal.'" name="nominal[]"></div><div class="col-md-4">Minimum : <input type="text" class="form-control" value="'.$type->min.'" name="min[]"></div>';
        echo '</div>';
        $cnt++;
        }
    }
    if($cat == 'tools')
    {
        if($type->category['name'] == "tools")
        {
        $cnt = 0;
        echo '<div class="form-group"><input type="hidden" name="row[]" value="'.$cnt.'"><input type="hidden" name="item[]" value="'.$type['name'].'">';
        echo '<div class="col-md-4"><strong>'.$type['name'].'</strong></div> <div class="col-md-4">Nominal : <input class="form-control" type="text" value="'.$type->nominal.'" name="nominal[]"></div><div class="col-md-4">Minimum : <input type="text" class="form-control" value="'.$type->min.'" name="min[]"></div>';
        echo '</div>';
        $cnt++;
        }
    }
    if($cat == 'clothes')
    {
        if($type->category['name'] == "clothes")
        {
        $cnt = 0;
        echo '<div class="form-group"><input type="hidden" name="row[]" value="'.$cnt.'"><input type="hidden" name="item[]" value="'.$type['name'].'">';
        echo '<div class="col-md-4"><strong>'.$type['name'].'</strong></div> <div class="col-md-4">Nominal : <input class="form-control" type="text" value="'.$type->nominal.'" name="nominal[]"></div><div class="col-md-4">Minimum : <input type="text" class="form-control" value="'.$type->min.'" name="min[]"></div>';
        echo '</div>';
        $cnt++;
        }
    }
}
if(isset($_GET['cat']))
{
   echo '<input type="hidden" name="catFile" value="'.$_GET['cat'].'.xml">';
   echo '<button type="submit" class="btn btn-block btn-info">CHANGE</button></form>';
}

这里有一些示例 XML 数据:

<types>
<type name="AK74_WoodBttstck">
        <nominal>5</nominal>
        <lifetime>14400</lifetime>
        <restock>0</restock>
        <min>2</min>
        <quantmin>-1</quantmin>
        <quantmax>-1</quantmax>
        <cost>100</cost>
        <flags count_in_cargo="0" count_in_hoarder="0" count_in_map="1" count_in_player="0" crafted="0" deloot="0"/>
        <category name="weapons"/>
        <usage name="Military"/>
    </type>
    <type name="AKM">
        <nominal>1</nominal>
        <lifetime>7200</lifetime>
        <restock>3600</restock>
        <min>1</min>
        <quantmin>30</quantmin>
        <quantmax>80</quantmax>
        <cost>100</cost>
        <flags count_in_cargo="0" count_in_hoarder="0" count_in_map="1" count_in_player="0" crafted="0" deloot="0"/>
        <category name="weapons"/>
        <usage name="ContaminatedArea"/>
    </type>
    <type name="AKS74U">
        <nominal>17</nominal>
        <lifetime>28800</lifetime>
        <restock>0</restock>
        <min>12</min>
        <quantmin>30</quantmin>
        <quantmax>80</quantmax>
        <cost>100</cost>
        <flags count_in_cargo="0" count_in_hoarder="0" count_in_map="1" count_in_player="0" crafted="0" deloot="0"/>
        <category name="weapons"/>
        <usage name="Military"/>
        <value name="Tier2"/>
        <value name="Tier3"/>
        <value name="Tier4"/>
    </type>
<type name="SpearBone">
        <nominal>0</nominal>
        <lifetime>14400</lifetime>
        <restock>0</restock>
        <min>0</min>
        <quantmin>-1</quantmin>
        <quantmax>-1</quantmax>
        <cost>100</cost>
        <flags count_in_cargo="0" count_in_hoarder="0" count_in_map="1" count_in_player="0" crafted="1" deloot="0"/>
        <category name="tools"/>
    </type>
    <type name="SpearStone">
        <nominal>0</nominal>
        <lifetime>14400</lifetime>
        <restock>0</restock>
        <min>0</min>
        <quantmin>-1</quantmin>
        <quantmax>-1</quantmax>
        <cost>100</cost>
        <flags count_in_cargo="0" count_in_hoarder="0" count_in_map="1" count_in_player="0" crafted="1" deloot="0"/>
        <category name="tools"/>
    </type>
    <type name="Splint">
        <nominal>0</nominal>
        <lifetime>14400</lifetime>
        <restock>0</restock>
        <min>0</min>
        <quantmin>-1</quantmin>
        <quantmax>-1</quantmax>
        <cost>100</cost>
        <flags count_in_cargo="0" count_in_hoarder="0" count_in_map="1" count_in_player="0" crafted="1" deloot="0"/>
        <category name="clothes"/>
    </type>
    <type name="Splint_Applied">
        <nominal>0</nominal>
        <lifetime>3</lifetime>
        <restock>0</restock>
        <min>0</min>
        <quantmin>-1</quantmin>
        <quantmax>-1</quantmax>
        <cost>100</cost>
        <flags count_in_cargo="0" count_in_hoarder="0" count_in_map="1" count_in_player="0" crafted="1" deloot="0"/>
        <category name="clothes"/>
    </type>
    <type name="SportGlasses_Black">
        <nominal>20</nominal>
        <lifetime>14400</lifetime>
        <restock>0</restock>
        <min>10</min>
        <quantmin>-1</quantmin>
        <quantmax>-1</quantmax>
        <cost>100</cost>
        <flags count_in_cargo="0" count_in_hoarder="0" count_in_map="1" count_in_player="0" crafted="0" deloot="0"/>
        <category name="clothes"/>
        <tag name="shelves"/>
        <usage name="Industrial"/>
        <usage name="Town"/>
        <usage name="Village"/>
        <usage name="Office"/>
        <usage name="School"/>
    </type>
</types>

编辑: 应该只是添加,例如 $cat='tools',而不是只保存项目 它存储所有类型的项目

我之前想让脚本根据类别名称创建单独的 XML 文件。 如果有人能帮我解决这个问题,那就容易多了

php xml simplexml
1个回答
0
投票

使用

json_encode()
将 SimpleXMLElement 转换为 JSON 通常会导致数据丢失。这会序列化 SimpleXMLElement 实例的调试输出。

使用 XML API 访问/操作 XML。我更喜欢DOM+Xpath。这允许针对特定节点和任何类型的操作(SimpleXML 是一种抽象且有限)。

对于 DOM,首先创建并加载文档。

$original = __DIR__.'/types.xml';
$edited = __DIR__.'/newTypes.xml';
$allowedCategories = ['weapons', 'tools', 'clothes'];

$document = new DOMDocument();
$document->load(file_exists($edited) ? $edited : $original);
$xpath = new DOMXpath($document);

Xpath 实例可用于获取节点(作为节点列表)或标量值 从文档中。这就是表单输出的样子:

<html>
  <body>
    <form action="./" method="post">
      <?php
        // iterate the "type" elements
        foreach ($xpath->evaluate('/types/type') as $typeNode) {
          // fetch the first "name" attribute of the "category" element as a string
          $category = $xpath->evaluate('string(category/@name)', $typeNode);
          if (!in_array($category, $allowedCategories)) {
            continue;
          }
          // read the name attribute of the current "type" element
          $itemName = $typeNode->getAttribute('name');
          // read the "nominal" child element as a number, cast to int
          $nominal =  (int)$xpath->evaluate('number(nominal)', $typeNode);
          // read the "min" child element as a number, cast to int
          $min =  (int)$xpath->evaluate('number(min)', $typeNode);
          // prepare the parameter name prefix - add "[someKey]" for each field
          $fieldPrefix = 'items['.htmlspecialchars($itemName).']';
          ?>
          <div class="form-group">
            <div class="col-md-4"><strong><?=htmlspecialchars($itemName)?></strong></div>
            <div class="col-md-4">Nominal : <input name="<?=$fieldPrefix?>[nominal]" class="form-control" type="text" value="<?=$nominal?>"></div>
            <div class="col-md-4">Minimum : <input name="<?=$fieldPrefix?>[min]" class="form-control" type="text" value="<?=$min?>"></div>
          </div>
          <?php
        }
      ?>
      <button>Save</button>
    </form>
  </body>
</html>

PHP 会将像

items[someName1][someKey1]
这样的参数名称解析为嵌套关联数组结构。这允许删除隐藏字段并降低复杂性。

<?=...>
是 PHP 短标签语法。添加它是为了使 PHP 模板更具可读性。

现在,如果您提交表单,

$_POST
将包含一个可以迭代的嵌套结构(以下代码应位于表单输出之前)。

$modified = false;
// check for the "items" parameter
if (isset($_POST['items']) && is_array($_POST['items'])) {
  // iterate it
  foreach ($_POST['items'] as $name => $data) {
    // fetch the "type" element with the matching "name" attribute
    $typeNode = $xpath->evaluate('/types/type[@name="'.$name.'"]')[0];
    // if found
    if ($typeNode) {
      // iterate the properties, use a whitelist
      foreach (['min', 'nominal'] as $propertyName) {
        // fetch the property node
        $propertyNode = $xpath->evaluate($propertyName, $typeNode)[0];
        // if node exists, data exists and the values are different
        if (
          $propertyNode &&
          $data[$propertyName] &&
          $propertyNode->textContent !== $data[$propertyName]
        ) {
          // update node content with parameter data
          $propertyNode->textContent = $data[$propertyName];
          $modified = true;
        }
      }
    }
  }
  // if a node was modified, save the document
  if ($modified) {
    $document->save($edited);
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.