Mishra Shreyanshu
Mishra Shreyanshu

Reputation: 644

Creating a XML from XML Value in PHP?

I am creating a XML from a string (This string is a value of another XML).

I tried simplexml_load_string to create.

My Scenerio:

My UI is in php and I am sending Excel sheet data through PHPExcel to my project's services part. It returns:

<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
   <root>
     <searcheddata>
         {Account0={AccountName=1, AddressLine2=0.0, Country=0.0, CellPhone=0.0, City=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, State=0.0, Zip=0.0, AlternateEmail=0.0},  City1={City=1, AddressLine2=0.0, Country=0.0, CellPhone=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, State=0.0, Zip=0.0, AlternateEmail=0.0},  State2={State=1, AddressLine2=0.0, Country=0.0, CellPhone=0.0, City=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, Zip=0.0, AlternateEmail=0.0},  Country3={Country=1, AddressLine2=0.0, CellPhone=0.0, City=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, State=0.0, Zip=0.0, AlternateEmail=0.0}}
        </searcheddata>
    </root>

Now I trying to create XML from the value of <searcheddata>.

Atlast I need a XML as:

<xml>
     <root>
        <Account0>
            <AccountName>1</AccountName>
            <AddressLine2>0.0</AddressLine2>
            <Country>0.0</Country>
            <CellPhone>0.0</CellPhone>
            <City>0.0</City>
            <WorkPhone>0.0</WorkPhone>
            <Other>0.0</Other>
            <HomePhone>0.0</HomePhone>
            <AddressLine1>0.0</AddressLine1>
            <State>0.0</State>
            <Zip>0.0</Zip>
            <AlternateEmail>0.0</AlternateEmail>
        </Account0>
        <City1>
            <City>1</City>
            <AddressLine2>0.0</AddressLine2>
            <Country>0.0</Country>
            <CellPhone>0.0</CellPhone>
            <WorkPhone>0.0</WorkPhone>
            <Other>0.0</Other>
            <HomePhone>0.0</HomePhone>
            <AddressLine1>0.0</AddressLine1>
            <State>0.0</State>
            <Zip>0.0</Zip>
            <AlternateEmail>0.0</AlternateEmail>
        </City1>
     </root>
 </xml>

What I tried:

<?php

$str = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><root><searcheddata>{Account0={AccountName=1, AddressLine2=0.0, Country=0.0, CellPhone=0.0, City=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, State=0.0, Zip=0.0, AlternateEmail=0.0},  City1={City=1, AddressLine2=0.0, Country=0.0, CellPhone=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, State=0.0, Zip=0.0, AlternateEmail=0.0},  State2={State=1, AddressLine2=0.0, Country=0.0, CellPhone=0.0, City=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, Zip=0.0, AlternateEmail=0.0},  Country3={Country=1, AddressLine2=0.0, CellPhone=0.0, City=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, State=0.0, Zip=0.0, AlternateEmail=0.0}}</searcheddata></root>";

$a = array();
$name = array();
$values = array();
$mainArray = array();
$xml = simplexml_load_string($str);
$s3 = $xml->searcheddata;
$pieces = (explode("},", $s3));
$pieces[0] = substr($pieces[0], 1);
$length = sizeof($pieces);
$pieces[$length - 1] = substr($pieces[$length - 1], 0, -2);
foreach ($pieces as $value) {
    $morePiece = (explode("={", $value));
    for ($i = 0; $i < sizeof($morePiece); $i = $i + 2) {
        $lastPiece = explode(", ", $morePiece[$i]);
        for ($j = 0; $j < sizeof($lastPiece); $j++) {
            array_push($a, $lastPiece[0]);
        }
    }
    for ($i = 1; $i < sizeof($morePiece); $i = $i + 2) {
        $lastPiece2 = explode(", ", $morePiece[$i]);
        for ($j = 0; $j < sizeof($lastPiece2); $j++) {
            $finalPiece2 = explode("=", $lastPiece2[$j]);
            for ($k = 0; $k < sizeof($finalPiece2); $k++) {
                if ($k % 2 == 0) {
                    array_push($name, $finalPiece2[$k]);
                } else {
                    array_push($values, $finalPiece2[$k]);
                }
            }
        }
    }
}
echo sizeof($pieces)."<br>";
print_r($a);
echo '<br><br>';
print_r($name);
echo '<br><br>';
print_r($values);
echo '<br><br>';
?>

I was trying to put all my key and value in respective array and then to create a XML using simplexml-load-string.

Suggestions are welcome.

Upvotes: 2

Views: 76

Answers (1)

mhall
mhall

Reputation: 3701

Trying hard to avoid writing a full parser, the following combines some regular expressions and conversions from different formats (string, JSON, array, SimpleXML and DOMDocument) to achieve the desired result.

I must admin it is a tiny bit hackish though - one current limitation, for example, is that values are required to be numeric as per your example (e.g. 123 or 123.45) - but may be enough in you case.

$source =<<<XML
<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
<root>
    <searcheddata>
        {Account0={AccountName=1, AddressLine2=0.0, Country=0.0, CellPhone=0.0, City=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, State=0.0, Zip=0.0, AlternateEmail=0.0},  City1={City=1, AddressLine2=0.0, Country=0.0, CellPhone=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, State=0.0, Zip=0.0, AlternateEmail=0.0},  State2={State=1, AddressLine2=0.0, Country=0.0, CellPhone=0.0, City=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, Zip=0.0, AlternateEmail=0.0},  Country3={Country=1, AddressLine2=0.0, CellPhone=0.0, City=0.0, WorkPhone=0.0, Other=0.0, HomePhone=0.0, Email=0.0, AddressLine1=0.0, State=0.0, Zip=0.0, AlternateEmail=0.0}}
    </searcheddata>
</root>
XML;

// Get rid of backslashes
$source = stripslashes($source);

// Create XML object, grab the data and remove whitespace
$xml  = new SimpleXMLElement($source);
$data = (string)$xml->searcheddata;
$data = preg_replace('/\s/', '', $data);

// Turn data into JSON:
// {foo={bar=1, baz=2.34}} => {"foo":{"bar":"1","baz":"2.34"}}
$data = preg_replace('/(\w+)=([\d\.]+)/', '"\1":"\2"', $data);
$data = preg_replace('/(\w+)=/',          '"\1":',     $data);

// Turn JSON into associative array
$decodedJson = json_decode($data, true);

// Function for adding array elements as XML child elements to XML element
function addElements(SimpleXMLElement $element, $a)
{
    foreach ($a as $key => $value) {
        if (is_array($value)) {
            $child = $element->addChild($key);
            addElements($child, $value);
        } else
            $element->addChild($key, $value);
    }
}

// Turn array into another Simple XML element and create <xml> and <root> tags
$simpleXml = new SimpleXMLElement('<xml/>');
$root      = $simpleXml->addChild('root');
addElements($root, $decodedJson);

// Pretty output by converting SimpleXML object to DOMElement
$dom = dom_import_simplexml($simpleXml)->ownerDocument;
$dom->formatOutput = true;
echo $dom->saveXML();

Output:

<?xml version="1.0"?>
<xml>
  <root>
    <Account0>
      <AccountName>1</AccountName>
      <AddressLine2>0.0</AddressLine2>
      <Country>0.0</Country>
      <CellPhone>0.0</CellPhone>
      <City>0.0</City>
      <WorkPhone>0.0</WorkPhone>
      <Other>0.0</Other>
      <HomePhone>0.0</HomePhone>
      <Email>0.0</Email>
      <AddressLine1>0.0</AddressLine1>
      <State>0.0</State>
      <Zip>0.0</Zip>
      <AlternateEmail>0.0</AlternateEmail>
    </Account0>
    <City1>
      <City>1</City>
      <AddressLine2>0.0</AddressLine2>
      <Country>0.0</Country>
      <CellPhone>0.0</CellPhone>
      <WorkPhone>0.0</WorkPhone>
      <Other>0.0</Other>
      <HomePhone>0.0</HomePhone>
      <Email>0.0</Email>
      <AddressLine1>0.0</AddressLine1>
      <State>0.0</State>
      <Zip>0.0</Zip>
      <AlternateEmail>0.0</AlternateEmail>
    </City1>
    ...
  </root>
</xml>

Upvotes: 2

Related Questions