Home > Blockchain >  move element into different element
move element into different element

Time:12-08

I have a xml. I want to have the element <Quantity> move into <WarehouseLine>

<?xml version="1.0"?>
<Container xmlns:ti="http://www.to-increase.com/data/blocks">
  <WarehouseHeader>
    <No>RMA-21001</No>
    <Description>RMA t.b.v. order_id #2</Description>
    <Duedate>17/11/2021</Duedate>
    <Quantity>1</Quantity>
    <WarehouseLine>
      <ItemNo>7890</ItemNo>
      <Description>Radiant Tee-L-Purple</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
    </WarehouseLine>
  </WarehouseHeader>
  <WarehouseHeader>
    <No>RMA-21003</No>
    <Description>RMA t.b.v. order_id #32</Description>
    <Duedate>02/12/2021</Duedate>
    <Quantity>1</Quantity>
    <WarehouseLine>
      <ItemNo>4560</ItemNo>
      <Description>Strive Shoulder Pack</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
    </WarehouseLine>
    <Quantity>1</Quantity>
    <WarehouseLine>
      <ItemNo>1234</ItemNo>
      <Description>Driven Backpack</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
    </WarehouseLine>
  </WarehouseHeader>
</Container>

I can do this with a foreach, but in my case the only first <Quantity> will be copied to <WarehouseLine>.

Code

$xml = simplexml_load_string($output);
$qty = $xml->WarehouseHeader->Quantity;
foreach ($xml->WarehouseHeader as $WarehouseHeader) {
    $child = $WarehouseHeader->WarehouseLine->addChild("Quantity", $qty);
}

echo $xml->asXML();

output

<?xml version="1.0"?>
<Container xmlns:ti="http://www.to-increase.com/data/blocks">
  <WarehouseHeader>
    <No>RMA-21001</No>
    <Description>RMA t.b.v. order_id #2</Description>
    <Duedate>17/11/2021</Duedate>
    <Quantity>1</Quantity>
    <WarehouseLine>
      <ItemNo>7890</ItemNo>
      <Description>Radiant Tee-L-Purple</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
    <Quantity>1</Quantity></WarehouseLine>
  </WarehouseHeader>
  <WarehouseHeader>
    <No>RMA-21003</No>
    <Description>RMA t.b.v. order_id #32</Description>
    <Duedate>02/12/2021</Duedate>
    <Quantity>1</Quantity>
    <WarehouseLine>
      <ItemNo>4560</ItemNo>
      <Description>Strive Shoulder Pack</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
    <Quantity>1</Quantity></WarehouseLine>
    <Quantity>1</Quantity> //next quantities
    <WarehouseLine>
      <ItemNo>1234</ItemNo>
      <Description>Driven Backpack</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
    </WarehouseLine>
  </WarehouseHeader>
</Container>

should be--- see <Quantity>1</Quantity> //next quantities

<?xml version="1.0"?>
<Container xmlns:ti="http://www.to-increase.com/data/blocks">
  <WarehouseHeader>
    <No>RMA-21001</No>
    <Description>RMA t.b.v. order_id #2</Description>
    <Duedate>17/11/2021</Duedate>
    <WarehouseLine>
      <ItemNo>7890</ItemNo>
      <Description>Radiant Tee-L-Purple</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
      <Quantity>1</Quantity>
    </WarehouseLine>
  </WarehouseHeader>
  <WarehouseHeader>
    <No>RMA-21003</No>
    <Description>RMA t.b.v. order_id #32</Description>
    <Duedate>02/12/2021</Duedate>
    <WarehouseLine>
      <ItemNo>4560</ItemNo>
      <Description>Strive Shoulder Pack</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
      <Quantity>1</Quantity>
    </WarehouseLine>
    <WarehouseLine>
      <ItemNo>1234</ItemNo>
      <Description>Driven Backpack</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
      <Quantity>1</Quantity>
    </WarehouseLine>
  </WarehouseHeader>
</Container>

CodePudding user response:

Here is XSLT based solution.

Two XSLT templates are doing what is needed:

  1. Supress Quantity elements on the WarehouseHeader element level.
  2. Move Quantity elements into the WarehouseLine element level.

Input XML

<?xml version="1.0"?>
<Container xmlns:ti="http://www.to-increase.com/data/blocks">
    <WarehouseHeader>
        <No>RMA-21001</No>
        <Description>RMA t.b.v. order_id #2</Description>
        <Duedate>17/11/2021</Duedate>
        <Quantity>1</Quantity>
        <WarehouseLine>
            <ItemNo>7890</ItemNo>
            <Description>Radiant Tee-L-Purple</Description>
            <UnitofMeasureCode>PCS</UnitofMeasureCode>
        </WarehouseLine>
    </WarehouseHeader>
    <WarehouseHeader>
        <No>RMA-21003</No>
        <Description>RMA t.b.v. order_id #32</Description>
        <Duedate>02/12/2021</Duedate>
        <Quantity>1</Quantity>
        <WarehouseLine>
            <ItemNo>4560</ItemNo>
            <Description>Strive Shoulder Pack</Description>
            <UnitofMeasureCode>PCS</UnitofMeasureCode>
        </WarehouseLine>
        <Quantity>8</Quantity>
        <WarehouseLine>
            <ItemNo>1234</ItemNo>
            <Description>Driven Backpack</Description>
            <UnitofMeasureCode>PCS</UnitofMeasureCode>
        </WarehouseLine>
    </WarehouseHeader>
</Container>

XSLT

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ti="http://www.to-increase.com/data/blocks">
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!--supress Quantity-->
    <xsl:template match="WarehouseHeader/Quantity"/>

    <!--bring Quantity from directly above-->
    <xsl:template match="WarehouseLine">
        <xsl:copy>
            <xsl:copy-of select="*"/>
            <xsl:copy-of select="preceding-sibling::Quantity[1]"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Output XML

<Container xmlns:ti="http://www.to-increase.com/data/blocks">
  <WarehouseHeader>
    <No>RMA-21001</No>
    <Description>RMA t.b.v. order_id #2</Description>
    <Duedate>17/11/2021</Duedate>
    <WarehouseLine>
      <ItemNo>7890</ItemNo>
      <Description>Radiant Tee-L-Purple</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
      <Quantity>1</Quantity>
    </WarehouseLine>
  </WarehouseHeader>
  <WarehouseHeader>
    <No>RMA-21003</No>
    <Description>RMA t.b.v. order_id #32</Description>
    <Duedate>02/12/2021</Duedate>
    <WarehouseLine>
      <ItemNo>4560</ItemNo>
      <Description>Strive Shoulder Pack</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
      <Quantity>1</Quantity>
    </WarehouseLine>
    <WarehouseLine>
      <ItemNo>1234</ItemNo>
      <Description>Driven Backpack</Description>
      <UnitofMeasureCode>PCS</UnitofMeasureCode>
      <Quantity>8</Quantity>
    </WarehouseLine>
  </WarehouseHeader>
</Container>

CodePudding user response:

Another option is to do sort of a cut and paste (or rather - copy, paste, delete) using xpath and simplexml:

$xml = simplexml_load_string($output);
#copy the quantities
$qtys = $xml->xpath('//WarehouseHeader//Quantity');
foreach ($qtys as $qty) {
   #locate the destination
   $dest = $qty->xpath('.//following-sibling::WarehouseLine')[0];
   #paste the quantity
   $dest->addChild("Quantity", $qty);
   #delete the original
   unset($qty[0]);
};
echo $xml->asXML();
  • Related