使用PHP将XML数据添加到不同的节点

时间:2018-06-06 15:51:23

标签: php xml

好的,我遇到了一个很大的问题,没有多少时间来修复它。我们有多个需要编辑的XML文件。我已经能够使用PHP获取数据,进行计算,并将其存储在变量中,但现在我被卡住了。我需要将该变量返回到XML文件中,但它会在文件中多次发生。以下是我的PHP代码:

<?php

//Change debug to value greater than 0 for debugging; make it greater than 5 for seeing all the arrays
$debug=0;

$file="test.xml";

$newfile = "filetemp.txt";
copy($file, $newfile) or exit("failed to copy $file");

$z = new XMLReader;
$z->open('test.xml');

$doc = new DOMDocument;

// move to the first <invoice /> node
while ($z->read() && $z->name !== 'invoice');

// now that we're at the right depth, hop to the next <invoice /> until the end of the tree
while ($z->name === 'invoice') {

  //the tot_array gathers the fund summary data into this array
  //this is needed in order to calculate the prorated shipping charges
  $tot_array=array();

  // either one should work
  //$node = new SimpleXMLElement($z->readOuterXML());
  $node = simplexml_import_dom($doc->importNode($z->expand(), true));

  if ($debug > 5) { print_r($node); }

  //initialize the check variable  
  $check=null;

  //this foreach checks for invoices that have "proratedByLine" - trying to reduce processing by reducing the number of records need to examine
  foreach ($node->invoiceLine as $atts) {
    if ($atts->attributes() == "proratedByLine") {
      if ($debug > 0) { echo "Yes", PHP_EOL; }
      $check="yes";
    } else {
      if ($debug > 0) { echo "No", PHP_EOL; }
      $check="no";
    }
  }
  if ($debug > 0) { echo "Check --> ".$check, PHP_EOL; }

  if ($check == "yes") {

    // now you can use $node without going insane about parsing
    //var_dump($node->invoiceID);
    echo "InvoiceID: ".$node->invoiceID, PHP_EOL;

    //this foreach assigns the $tot_array variable the fund summary data from the invoice
    foreach ($node->fundSummary->fund as $funds) {
      $tot_array["$funds->fundID"]=$funds->amountPaid;
    }

    //initialize $x, $y, and $sortable_array variables;
    $x=0; $y=0; $sortable_array=null;

    //assign sortable_array variable as an array
    $sortable_array=array();

    //this foreach stores the individual invoiceLine "fundId | amout paid" into an array, to be used to compare with the fund summary array (tot_array)
    foreach ($node->invoiceLine as $atts) {
      if ($debug > 5) { print_r($atts); }
      if ($atts->attributes() == "orderLine") {
        if ($debug > 0) { echo "FundID: ".$atts->fundID,PHP_EOL; }
        $sortable_array["$x"]=$atts->fundID."|".$atts->amountInvoiced->vendorAmountPaid;
        $xx=$atts->fundID;
      }
      $x=$x+1;
    }

    //this count variable is used to find the last invoiceLine in the invoice - always the prorated line (shipping)
    $count=$x-1;
    if ($debug > 0) { echo "Count: ".$count, PHP_EOL; }

    //need to sort the "fundId|amount paid" array in order to calculate total
    sort($sortable_array);

    if ($debug > 5) { print_r($tot_array); print_r($sortable_array); }

    //this section sums the "fundId|amount paid" into the fund2 array
    $xx=0;
    $x=null;
    $tot=0;
    $fund2=array();
    foreach($sortable_array as $key=>$value) {
      if ($debug > 0) { echo "key: ".$key."; value: ".$value, PHP_EOL; }
      list($fund,$amt)=explode("|",$value);
      if ($fund == $x) {
        $tot=$tot+$amt;
        if ($debug > 0) { echo "Fund1: ".$fund."; Amount: ".$tot, PHP_EOL; }
      } else {
        $tot=$amt;
        $x=$fund;
        if ($debug > 0) { echo "Fund2: ".$fund."; Amount: ".$amt, PHP_EOL; }
      }
      $fund2["$x"]=$tot;
    }

    if ($debug > 5) { print_r($fund2); }

    //this section calculates the actual prorated shipping charges per fund and stores it in the $entry variable as XML
    //initialize the prov, insert, entry, library, fyear, and entry variables
    $prov=0; $insert=array(); $entry=null; $library=null; $fyear=null; $entry=PHP_EOL;
    foreach($tot_array as $key=>$value) {
      if ($debug > 0) { echo "Key: ".$key."; Value: ".$value, PHP_EOL; }
      foreach($fund2 as $key2=>$value2) {
        if ($debug > 0) { echo "Key2: ".$key2."; Value2: ".$value2, PHP_EOL; }
        if ($key == $key2) {
          //have to assign the value variables to the float type in order to calculate correctly
          settype($value, "float");
          settype($value2, "float");
          if ($debug > 0) { echo "Value (".$value.") minus Value2 (".$value2.")",PHP_EOL; }
          $prov=$value-$value2;
          $entry .= "<fundID>".$key."</fundID>".PHP_EOL;
          $entry .= "<fundLibrary>".$library."</fundLibrary>".PHP_EOL;
          $entry .= "<fiscalCycle>".$fyear."</fiscalCycle>".PHP_EOL;
          $entry .= "<vendorFinalPrice currency=\"$\">".$prov."</vendorFinalPrice>".PHP_EOL;
        }
      }
    }

/*
//None of the below works
foreach($lines as $line) {
  if (strstr($line,$key)) { //look for $key in each
    fwrite($f,$newline."\n"); //insert data before line with key
  }
  fwrite($f,$line); //place $line back in file
}

$string = 'I am happy today.';
$replacement = 'very ';
echo substr_replace($string, $replacement, 4, 0); // I am very happy today.

//appendChild not available in Windows version of PHP
$node->invoiceLine[$count]->appendChild('funds', $entry);

//the below two lines wipes out the original file and only maintains the last invoice with the changes; can't do that
$node->invoiceLine[$count]->funds = $entry;
$node->asXML($file);

//the below works in Linux but not Windows
$cmd = "cat $file| sed -e 's/&lt;/</g' -e 's/&gt;/>/g' > newfile.txt";
$cmd2 = "mv newfile.txt $file";
exec($cmd);
exec($cmd2);
*/

  } //end invoice check for prorated line

  // go to next <invoice />
  $z->next('invoice');

} //end while statement 

//the below line does not work - only inserts the last invoice into the file; does not include all invoices from the file
//$node->asXML($file);

?>

这是我正在反对的XML:

<?xml version="1.0" encoding="UTF-8"?>
  <report>
  <dateCreated>2018-05-29T16:04:22</dateCreated>
  <dateFormat>mm/dd/yyyy</dateFormat>
<invoice>
  <library>BIOMEDICAL</library>
  <invoiceID>A530303</invoiceID>
  <vendorID>MAJORSB</vendorID>
  <invoiceControlNumber>          1</invoiceControlNumber>
  <createdInFiscalCycle>1997</createdInFiscalCycle>
  <fundSummary>
  <fund>
  <fundID>48020000</fundID>
  <fiscalCycle>1997</fiscalCycle>
  <accountNumber>1536950000,74500</accountNumber>
  <amountInvoiced currency="$">0.00</amountInvoiced>
  <amountPaid currency="$">373.88</amountPaid>
  </fund>
  </fundSummary>
  <numberOfLines>6</numberOfLines>
  <numberOfLinesPaid>6</numberOfLinesPaid>
  <numberOfCopies>6</numberOfCopies>
  <numberOfCopiesPaid>6</numberOfCopiesPaid>
  <invoiceLine lineType="orderLine">
  <lineNumber>1</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">35.16</vendorAmount>
  <vendorAmountPaid currency="$">35.16</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF5423001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">35.16</vendorFinalPrice>
    <orderlineKey>001AHF5423001_1997_1</orderlineKey>
    <fundID>48020000</fundID>
    <fundLibrary>BIOMEDICAL</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>2</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">52.76</vendorAmount>
  <vendorAmountPaid currency="$">52.76</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF5486001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">52.76</vendorFinalPrice>
    <orderlineKey>001AHF5486001_1997_1</orderlineKey>
    <fundID>48020000</fundID>
    <fundLibrary>BIOMEDICAL</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>3</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">70.40</vendorAmount>
  <vendorAmountPaid currency="$">70.40</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF5492001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">70.40</vendorFinalPrice>
    <orderlineKey>001AHF5492001_1997_1</orderlineKey>
    <fundID>48020000</fundID>
    <fundLibrary>BIOMEDICAL</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>4</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">43.96</vendorAmount>
  <vendorAmountPaid currency="$">43.96</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF5493001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">43.96</vendorFinalPrice>
    <orderlineKey>001AHF5493001_1997_1</orderlineKey>
    <fundID>48020000</fundID>
    <fundLibrary>BIOMEDICAL</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>5</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">61.60</vendorAmount>
  <vendorAmountPaid currency="$">61.60</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF7077001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">61.60</vendorFinalPrice>
    <orderlineKey>001AHF7077001_1997_1</orderlineKey>
    <fundID>48020000</fundID>
    <fundLibrary>BIOMEDICAL</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>6</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">110.00</vendorAmount>
  <vendorAmountPaid currency="$">110.00</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF7085001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">110.00</vendorFinalPrice>
    <orderlineKey>001AHF7085001_1997_1</orderlineKey>
    <fundID>48020000</fundID>
    <fundLibrary>BIOMEDICAL</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
</invoice>
<invoice>
  <library>VU-PROCESS</library>
  <invoiceID>106543</invoiceID>
  <vendorID>7828</vendorID>
  <invoiceControlNumber>          3</invoiceControlNumber>
  <createdInFiscalCycle>1997</createdInFiscalCycle>
  <total>
  <vendorAmount currency="$">235.80</vendorAmount>
  <vendorAmountPaid currency="$">235.80</vendorAmountPaid>
  </total>
  <dateCreated>1996-08-14</dateCreated>
  <dateModified>1996-08-20</dateModified>
  <dateInvoiced>1996-06-14</dateInvoiced>
  <extendedInfo>
  <entry name="Note">mew</entry>
  </extendedInfo>
  <fundSummary>
  <fund>
  <fundID>23022300</fundID>
  <fiscalCycle>1997</fiscalCycle>
  <accountNumber>1532200000,74500</accountNumber>
  <amountInvoiced currency="$">0.00</amountInvoiced>
  <amountPaid currency="$">102.53</amountPaid>
  </fund>
  <fund>
  <fundID>23023700</fundID>
  <fiscalCycle>1997</fiscalCycle>
  <accountNumber>1534310000,74500</accountNumber>
  <amountInvoiced currency="$">0.00</amountInvoiced>
  <amountPaid currency="$">27.27</amountPaid>
  </fund>
  <fund>
  <fundID>23024400</fundID>
  <fiscalCycle>1997</fiscalCycle>
  <accountNumber>1532200000,74500</accountNumber>
  <amountInvoiced currency="$">0.00</amountInvoiced>
  <amountPaid currency="$">70.55</amountPaid>
  </fund>
  <fund>
  <fundID>23028800</fundID>
  <fiscalCycle>1997</fiscalCycle>
  <accountNumber>1532200000,74500</accountNumber>
  <amountInvoiced currency="$">0.00</amountInvoiced>
  <amountPaid currency="$">35.45</amountPaid>
  </fund>
  </fundSummary>
  <numberOfLines>9</numberOfLines>
  <numberOfLinesPaid>9</numberOfLinesPaid>
  <numberOfCopies>8</numberOfCopies>
  <numberOfCopiesPaid>8</numberOfCopiesPaid>
  <invoiceLine lineType="orderLine">
  <lineNumber>1</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">30.00</vendorAmount>
  <vendorAmountPaid currency="$">30.00</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF3988001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">30.00</vendorFinalPrice>
    <orderlineKey>001AHF3988001_1997_1</orderlineKey>
    <fundID>23024400</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>2</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">18.95</vendorAmount>
  <vendorAmountPaid currency="$">18.95</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHE9316001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">18.95</vendorFinalPrice>
    <orderlineKey>001AHE9316001_1997_1</orderlineKey>
    <fundID>23028800</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>3</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">17.00</vendorAmount>
  <vendorAmountPaid currency="$">17.00</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHE5275001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">17.00</vendorFinalPrice>
    <orderlineKey>001AHE5275001_1997_1</orderlineKey>
    <fundID>23022300</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>4</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">26.50</vendorAmount>
  <vendorAmountPaid currency="$">26.50</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF1062001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">26.50</vendorFinalPrice>
    <orderlineKey>001AHF1062001_1997_1</orderlineKey>
    <fundID>23023700</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>5</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">23.25</vendorAmount>
  <vendorAmountPaid currency="$">23.25</vendorAmountPaid>
  </amountInvoiced>
   <orderID>001AHE2367001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">23.25</vendorFinalPrice>
    <orderlineKey>001AHE2367001_1997_1</orderlineKey>
    <fundID>23022300</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>6</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">39.00</vendorAmount>
  <vendorAmountPaid currency="$">39.00</vendorAmountPaid>
  </amountInvoiced>
  <orderID>002AHC0935001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">39.00</vendorFinalPrice>
    <orderlineKey>002AHC0935001_1997_1</orderlineKey>
    <fundID>23024400</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>7</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">14.95</vendorAmount>
  <vendorAmountPaid currency="$">14.95</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHE9312001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">14.95</vendorFinalPrice>
    <orderlineKey>001AHE9312001_1997_1</orderlineKey>
    <fundID>23028800</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>8</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">59.95</vendorAmount>
  <vendorAmountPaid currency="$">59.95</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF2201001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">59.95</vendorFinalPrice>
    <orderlineKey>001AHF2201001_1997_1</orderlineKey>
    <fundID>23022300</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="proratedByLine">
  <lineNumber>SHIPPING</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">6.20</vendorAmount>
  <vendorAmountPaid currency="$">6.20</vendorAmountPaid>
  </amountInvoiced>
  </invoiceLine>
</invoice>
<invoice>
  <library>VU-PROCESS</library>
  <invoiceID>106551</invoiceID>
  <vendorID>7828</vendorID>
  <invoiceControlNumber>          5</invoiceControlNumber>
  <createdInFiscalCycle>1997</createdInFiscalCycle>
  <total>
  <vendorAmount currency="$">524.27</vendorAmount>
  <vendorAmountPaid currency="$">524.27</vendorAmountPaid>
  </total>
  <dateCreated>1996-08-14</dateCreated>
  <dateModified>1996-08-20</dateModified>
  <dateInvoiced>1996-06-14</dateInvoiced>
  <extendedInfo>
  <entry name="Note">mew</entry>
  </extendedInfo>
  <fundSummary>
  <fund>
  <fundID>46024600</fundID>
  <fiscalCycle>1997</fiscalCycle>
  <accountNumber>1532200000,74500</accountNumber>
  <amountInvoiced currency="$">0.00</amountInvoiced>
  <amountPaid currency="$">524.27</amountPaid>
  </fund>
  </fundSummary>
  <numberOfLines>7</numberOfLines>
  <numberOfLinesPaid>7</numberOfLinesPaid>
  <numberOfCopies>6</numberOfCopies>
  <numberOfCopiesPaid>6</numberOfCopiesPaid>
  <invoiceLine lineType="orderLine">
  <lineNumber>1</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">118.75</vendorAmount>
  <vendorAmountPaid currency="$">118.75</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF2309001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">118.75</vendorFinalPrice>
    <orderlineKey>001AHF2309001_1997_1</orderlineKey>
    <fundID>46024600</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>2</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">80.75</vendorAmount>
  <vendorAmountPaid currency="$">80.75</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF2311001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">80.75</vendorFinalPrice>
    <orderlineKey>001AHF2311001_1997_1</orderlineKey>
    <fundID>46024600</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>3</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">85.45</vendorAmount>
  <vendorAmountPaid currency="$">85.45</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF2369001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">85.45</vendorFinalPrice>
    <orderlineKey>001AHF2369001_1997_1</orderlineKey>
    <fundID>46024600</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>4</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">85.45</vendorAmount>
  <vendorAmountPaid currency="$">85.45</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF2313001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">85.45</vendorFinalPrice>
    <orderlineKey>001AHF2313001_1997_1</orderlineKey>
    <fundID>46024600</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>5</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">94.95</vendorAmount>
  <vendorAmountPaid currency="$">94.95</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF2325001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">94.95</vendorFinalPrice>
    <orderlineKey>001AHF2325001_1997_1</orderlineKey>
    <fundID>46024600</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="orderLine">
  <lineNumber>6</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">45.13</vendorAmount>
  <vendorAmountPaid currency="$">45.13</vendorAmountPaid>
  </amountInvoiced>
  <orderID>001AHF2368001</orderID>
  <fiscalCycle>1997</fiscalCycle>
  <orderLineNumber>1</orderLineNumber>
  <numberOfCopies>1</numberOfCopies>
  <vendorFinalPrice currency="$">45.13</vendorFinalPrice>
    <orderlineKey>001AHF2368001_1997_1</orderlineKey>
    <fundID>46024600</fundID>
    <fundLibrary>VU-PROCESS</fundLibrary>
    <fiscalCycle>1997</fiscalCycle>
  </invoiceLine>
  <invoiceLine lineType="proratedByLine">
  <lineNumber>SHIPPING</lineNumber>
  <amountInvoiced>
  <vendorAmount currency="$">13.79</vendorAmount>
  <vendorAmountPaid currency="$">13.79</vendorAmountPaid>
  </amountInvoiced>
  </invoiceLine>
</invoice>
</report>

1 个答案:

答案 0 :(得分:0)

XMLReader用于逐个读取大型XML文档。这意味着您无法修改原始内容 - 它永远不会作为一个整体提供。缺少的组件是XMLWriter。通过invoice读取源XML invoice并创建该文件的修改副本。此外,这种方法是可重复的,如果出现问题,不会破坏原始数据。

XMLReader::expand()从XMLReader创建DOM结构。修改节点并使用XMLWriter将它们写入目标文档。

为了让我更容易,我在FluentDOM(我自己的PHP XML库)中为XMLWriter添加了一个collapse()方法。

使用FluentDOM代码可能如下所示:

// load the source into a reader
$reader = new \FluentDOM\XMLReader();
$reader->open(__DIR__.'/test.xml');

// create a writer instance for the target file
$writer = new \FluentDOM\XMLWriter();
$writer->openUri(__DIR__.'/test-output.xml');
$writer->setIndent(2);
$writer->startDocument();
$writer->startElement('report');

// iterate the invoice elements
/** @var \FluentDOM\DOM\Element $invoiceNode */
foreach (new FluentDOM\XMLReader\SiblingIterator($reader, 'invoice') as $invoiceNode) {

  // fetch the proratedByLine invoiceLine as target node
  /** @var \FluentDOM\DOM\Element|NULL $shippingNode */
  $shippingNode = $invoiceNode->evaluate('invoiceLine[@lineType = "proratedByLine"]')[0];

  // if here is a shipping line, check and modify
  if ($shippingNode) {

    echo 'InvoiceID: '.$invoiceNode->evaluate('string(invoiceID)'), PHP_EOL;

    // collect the fundSummary by fundId
    $currentTotals = [];
    /** @var \FluentDOM\DOM\Element $fund */
    foreach ($invoiceNode->evaluate('fundSummary/fund') as $fund) {
      $totals[$fund->evaluate('string(fundID)')] = $fund->evaluate('number(amountPaid)');
    }

    // iterate all orderLine values and sum them up grouped by fund ID
    $vendorPaid = [];
    /** @var \FluentDOM\DOM\Element $line */
    foreach ($invoiceNode->evaluate('invoiceLine[@lineType = "orderLine"]') as $line) {
      $fundID = $line->evaluate('string(fundID)');
      if (!isset($lines[$fundID])) {
        $vendorPaid[$fundID] = 0;
      }
      $vendorPaid[$fundID] += $line->evaluate('number(amountInvoiced/vendorAmountPaid)');
    }

    // build a list with all fundIDs
    $fundIDs = array_merge(array_keys($currentTotals), array_keys($vendorPaid));

    // iterate over them
    foreach ($fundIDs as $fundID) {
      // calculate the new value
      $totalValue = $currentTotals[$fundID] ?? 0.0;
      $vendorValue = $vendorPaid[$fundID] ?? 0.0;
      $value = number_format($totalValue - $vendorValue, 2);

      // modify the $targetNode or $invoiceNode as needed
      // for example add the values as a new element to the $shippingNode
      $entry = $shippingNode->appendElement('calculated-entry');
      $entry->appendElement('fundID', $fundID);
      $entry->appendElement('vendorFinalPrice', $value, ['currency'=> '$']);
    }
  }

  // collapse/write the invoice element into the target file
  $writer->collapse($invoiceNode);
}

$writer->endElement();
$writer->endDocument();