使用 PHP 生成正确的 XML 文件时出现问题

Problems in generating proper XML file using PHP

我正在尝试使用 PHP 动态生成/更新 XML 文件。下面是我要的XML文件的结构:

test1.xml

<?xml version="1.0" encoding="UTF-8"?>
<month month_no="2">
  <dailytotal date="2018-02-28">10</dailytotal>
  <monthlytotal>10</monthlytotal>
</month>

dailytotal 元素存储每天的总值(由 date 属性指示),monthlytotal 元素存储每个月的总值(dailytotals)。 monthmonth_no 属性指示。

我面临的问题是,当我在属于不同月份(例如 month_no="3")的日期生成 XML 文件时,该文件被覆盖并且其之前的所有内容都消失了.

我尝试搜索任何可能的问题(例如,在处理 XML 文档的 DOM 树时)但我找不到任何问题,而且我的代码逻辑似乎是正确的!

此外,当我再次 运行 相同的脚本时,我收到一条警告消息,我不明白为什么会收到它。

Warning: DOMDocument::load(): Extra content at the end of the document in file:/C:/xampp/htdocs/DailyExpenseCalculator/test1.xml, line: 6 in C:\xampp\htdocs\DailyExpenseCalculator\xml_modify.php on line 8

我认为警告是由于文件中有一个额外的换行符,但删除它不起作用。

xml_generator.php

<?php
    // Loading the XML file and updating data to it
    $date = date('Y-m-d');
    $balanceObj = 10;
    $doc = new DOMDocument("1.0", "UTF-8");

    $doc->preserveWhiteSpace = false;
    $doc->formatOutput = true;

    $doc->load('test1.xml');

    $months = $doc->getElementsByTagName('month');

    $cur_month = (int) date('m');
    $cur_date = $date;

    $found_month = false;
    //echo "<p>Current date: ".$cur_date."</p>";
    //echo "<p>Current month: ".$cur_month."</p>";

    foreach($months as $month) {
        $month_no = (int) $month->getAttribute('month_no');

        if($cur_month == $month_no) {
            //echo "<p>Found month</p>";
            $dailytotals = $month->getElementsByTagName('dailytotal');
            $found_date = false;

            foreach($dailytotals as $d) {
                $this_date = $d->getAttribute('date');

                if($this_date === $cur_date) {
                    // echo "<p>Found date</p>";
                    $new_dailytotal = $doc->createElement('dailytotal', (float) $balanceObj);
                    $new_dailytotal->setAttribute('date', $date);
                    $d->parentNode->replaceChild($new_dailytotal, $d);  // (new node, old node)
                    $found_date = true;
                    break;
                }
            }

            if($found_date == false) {  // entry on a new day
                //echo "<p>Didn't found date</p>";
                $newDailyTotal = $doc->createElement('dailytotal', (float) $balanceObj);
                $newDailyTotal->setAttribute('date', $date);
                $m = $month->getElementsByTagName('monthlytotal')->item(0);
                $newBalance = ((float) $m->nodeValue) + ((float) $balanceObj);
                $newMonthlyTotal = $doc->createElement('monthlytotal', (float) $newBalance);
                $m->parentNode->replaceChild($newMonthlyTotal, $m);
                $newDailyTotal = $month->appendChild($newDailyTotal);
            }

            else {                      // entry on the same day
                $m = $month->getElementsByTagName('monthlytotal')->item(0);
                // $oldBalance = (float) $m->nodeValue;
                // $newBalance = $oldBalance - $oldDailyTotal + $balanceObj;
                $newBalance = ((float) $m->nodeValue) + ((float) $balanceObj);
                $newMonthlyTotal = $doc->createElement('monthlytotal', (float) $newBalance);
                $m->parentNode->replaceChild($newMonthlyTotal, $m);
            }

            $found_month = true;
            break;
        }
    }

    if($found_month == false) {
        // echo "<p>Didn't found month</p>";
        $newMonthElement = $doc->createElement('month');
        $newMonthElement->setAttribute('month_no', $cur_month);
        $newDailyTotalElement = $doc->createElement('dailytotal', (float) $balanceObj);
        $newDailyTotalElement->setAttribute('date', $date);
        $newMonthlyTotalElement = $doc->createElement('monthlytotal', (float) $balanceObj);
        $newDailyTotalElement = $newMonthElement->appendChild($newDailyTotalElement);
        $newMonthlyTotalElement = $newMonthElement->appendChild($newMonthlyTotalElement);
        $newMonthElement = $doc->appendChild($newMonthElement);
    }

    $doc->save('test1.xml');
?>

您需要一个根节点来放置您的 <month> 标签。

首先,更改您的首字母 XML :

<?xml version="1.0" encoding="UTF-8"?>
<months>
    <month month_no="2">
        <dailytotal date="2018-02-28">10</dailytotal>
        <monthlytotal>10</monthlytotal>
    </month>
</months>

然后,在加载您的 XML 之后:

$months_tags = $doc->getElementsByTagName('months');
$months_tag = $months_tags[0];

最后,将您的月份标签放入根节点:

$months_tag->appendChild($newMonthElement);

完整代码:(检查 /// <<< CHANGE

// Loading the XML file and updating data to it
$date = date('Y-m-d');
$balanceObj = 10;
$doc = new DOMDocument("1.0", "UTF-8");

$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;

$doc->load('test1.xml');

$months_tags = $doc->getElementsByTagName('months'); /// <<< CHANGE
$months_tag = $months_tags[0]; /// <<< CHANGE

$months = $doc->getElementsByTagName('month');

$cur_month = (int) date('m');
$cur_date = $date;

$found_month = false;
echo "<p>Current date: ".$cur_date."</p>";
echo "<p>Current month: ".$cur_month."</p>";

foreach($months as $month) {
    $month_no = (int) $month->getAttribute('month_no');

    if($cur_month == $month_no) {
        echo "<p>Found month</p>";
        $dailytotals = $month->getElementsByTagName('dailytotal');
        $found_date = false;

        foreach($dailytotals as $d) {
            $this_date = $d->getAttribute('date');

            if($this_date === $cur_date) {
               echo "<p>Found date</p>";
                $new_dailytotal = $doc->createElement('dailytotal', (float) $balanceObj);
                $new_dailytotal->setAttribute('date', $date);
                $d->parentNode->replaceChild($new_dailytotal, $d);  // (new node, old node)
                $found_date = true;
                break;
            }
        }

        if($found_date == false) {  // entry on a new day
            echo "<p>Didn't found date</p>";
            $newDailyTotal = $doc->createElement('dailytotal', (float) $balanceObj);
            $newDailyTotal->setAttribute('date', $date);
            $m = $month->getElementsByTagName('monthlytotal')->item(0);
            $newBalance = ((float) $m->nodeValue) + ((float) $balanceObj);
            $newMonthlyTotal = $doc->createElement('monthlytotal', (float) $newBalance);
            $m->parentNode->replaceChild($newMonthlyTotal, $m);
            $newDailyTotal = $month->appendChild($newDailyTotal);
        }

        else {                      // entry on the same day
            $m = $month->getElementsByTagName('monthlytotal')->item(0);
            // $oldBalance = (float) $m->nodeValue;
            // $newBalance = $oldBalance - $oldDailyTotal + $balanceObj;
            $newBalance = ((float) $m->nodeValue) + ((float) $balanceObj);
            $newMonthlyTotal = $doc->createElement('monthlytotal', (float) $newBalance);
            $m->parentNode->replaceChild($newMonthlyTotal, $m);
        }

        $found_month = true;
        break;
    }
}

if($found_month == false) {

    echo "<p>Didn't found month</p>";
    $newMonthElement = $doc->createElement('month');
    $newMonthElement->setAttribute('month_no', $cur_month);
    $newDailyTotalElement = $doc->createElement('dailytotal', 2);
    $newDailyTotalElement->setAttribute('date', $date);
    $newMonthlyTotalElement = $doc->createElement('monthlytotal', 3);
    $newDailyTotalElement = $newMonthElement->appendChild($newDailyTotalElement);
    $newMonthlyTotalElement = $newMonthElement->appendChild($newMonthlyTotalElement);
    $months_tag->appendChild($newMonthElement); /// <<< CHANGE
}

$doc->save('test1.xml');