douzao1119 2018-06-06 15:51
浏览 50

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

OK, I am having a huge problem and have little time to fix it. We have multiple XML files that need to be edited. I've been able to grab the data using PHP, do the calculation, and store it in a variable, but now I am stuck. I need to get that variable back into the XML file, but it will happen multiple times in the file. Here is what I have for my PHP code:

<?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."
"); //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);

?>

And here is the XML I am working against:

<?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条回答 默认 最新

  • dongye9191 2018-06-06 19:54
    关注

    XMLReader is used to read a large XML document part by part. This means you can not modify the original - it is never available as a whole. The missing component is XMLWriter. Read the source XML invoice by invoice and create a modified copy of the file. Additionally this approach is repeatable and does not destroy your original data if something goes wrong.

    XMLReader::expand() creates a DOM structure from the XMLReader. Modify the nodes and write them into the target document using XMLWriter.

    To make that easier for me, I added a collapse() method to XMLWriter in FluentDOM (My own XML libary for PHP).

    Using FluentDOM the code could look like this:

    // 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();
    
    评论

报告相同问题?

悬赏问题

  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100
  • ¥15 关于#hadoop#的问题
  • ¥15 (标签-Python|关键词-socket)
  • ¥15 keil里为什么main.c定义的函数在it.c调用不了
  • ¥50 切换TabTip键盘的输入法
  • ¥15 可否在不同线程中调用封装数据库操作的类
  • ¥15 微带串馈天线阵列每个阵元宽度计算
  • ¥15 keil的map文件中Image component sizes各项意思