hey there,

in Java, I can take a text file and build a two dimensional array out of it. I hope I can do that in PHP as well but I can't seem to be able to do it.

these are the specifics of my problem:

I have an xml file. for simplicity:

<person>
   <name>john</name>
   <last>smith</last>
</person>
<person>
   <name>ana</name>
   <last>smith</last>
</person>

I want to generate a two dimensional array, such that it's first row contains the array (<person>, <name>john</name>,<last>smith</last>, </person>) and it's second row contains (<person>, <name>ana</name>,<last>smith</last>, </person>)


what I tried is this:

//I use $end_delimit to know when to move to the next row of my two-dimensional array
	function xmlToAray($file, $end_delimit){
		$rez = array();
		$lines = file($file);
		$k = 0;//
		$rows = array();
		for($i = 0; $i < sizeOf($lines); $i++){
			array_push($rows[$k], $lines[$i]);
			if(strrpos($lines[$i],$end_delimit) === 0 || strrpos($lines[$i], $end_delimit) === 0){
				$rez[$k] = $rows;
				$k++;
			}
		}
		return $rez;
	}

what I get is a complaint: array_push() expects parameter 1 to be array, null given... I understand what this means, but I don't know how to avoid it. can you please tell me. thank you!

Dani AI

Generated

line-by-line parsing is what is biting you here. Even with pointing out the missing array init, matching tags by column 0 and manual delimiters will break on indentation, blank lines, or mixed content. Also, your sample XML is not well-formed because it has multiple top-level elements; XML parsers expect a single root element. Parse the XML with SimpleXML (or DOM) and then build the 2D array from nodes.

Example: build a 2D array of values (safer for later processing).

$xmlString = file_get_contents('people.xml');
$xml = simplexml_load_string('<root>'.$xmlString.'</root>', 'SimpleXMLElement', LIBXML_NOBLANKS|LIBXML_NOCDATA);
// If your file already has a single root (e.g., <people>...</people>), use simplexml_load_file('people.xml') instead.

$rows = [];
foreach ($xml->person as $p) {
    $rows[] = [(string)$p->name, (string)$p->last];
}
// $rows === [['john','smith'], ['ana','smith']]

If you truly need each row to contain literal tag fragments as strings (as in your question), you can still let the parser do the heavy lifting and then format the pieces:

$rowsWithTags = [];
foreach ($xml->person as $p) {
    $rowsWithTags[] = [
        '<person>',
        $p->name->asXML(),   // "<name>john</name>"
        $p->last->asXML(),   // "<last>smith</last>"
        '</person>',
    ];
}

Notes:

  • Using asXML() preserves the element markup consistently, regardless of whitespace in the source.
  • Avoid tokenizing XML by lines; it is fragile and hard to maintain.
  • For huge XML files, consider streaming with XMLReader and assembling rows on the fly to keep memory low.

Recommended Answers

All 3 Replies

Just add

$rows[$k] = array();

in between lines 7 and 8.

thank you for your reply Insensus. I am sorry to say that that won't work either because $rows in that case will be null. however, I solved my problem. this is how:

function xmlToAray($file, $end_delimit){
		$s = sizeOf(file("elementet.txt"));
		for($t = 0; $t < $s; $t++){
			$rez[$t] = array("<anetari>");
		}
		$lines = file($file);//array; hold file
		$k = 0;//counts rows for $rows
		$rows;
		$count = 0;//counts rows for $rez
		for($i = 0; $i < sizeOf($lines); $i++){
				$rows[$k] = $lines[$i];
				$k++;
				if(strrpos($lines[$i], $end_delimit) === 0){//once the end of the xml element is reached
					$k = 0;//start a new row
					$rez[$count] = $rows;//save current row on the two-dimensional array
					$count++;//prepare next row of the (main) two-dimensional array
				}
		}
		return $rez;
	}

In your original code $rows wasn't null because of line 6:

$rows = array();

But good you fixed it yourself.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.