Michael
Michael

Reputation: 6405

php associative arrays, regex, array

I currently have the following code :

$content = "
<name>Manufacturer</name><value>John Deere</value><name>Year</name><value>2001</value><name>Location</name><value>NSW</value><name>Hours</name><value>6320</value>";

I need to find a method to create and array as name=>value. E.g Manufacturer => John Deere.

Can anyone help me with a simple code snipped I tried some regex but doesn't even work to extract the names or values, e.g.:

$pattern = "/<name>Manufacturer<\/name><value>(.*)<\/value>/";
preg_match_all($pattern, $content, $matches);
$st_selval = $matches[1][0];

Upvotes: 0

Views: 2076

Answers (7)

Arturo
Arturo

Reputation: 1131

I think this is what you're looking for:

<?php
$content = "<name>Manufacturer</name><value>John Deere</value><name>Year</name><value>2001</value><name>Location</name><value>NSW</value><name>Hours</name><value>6320</value>";
$pattern = "(\<name\>(\w*)\<\/name\>\<value\>(\w*)\<\/value\>)";
preg_match_all($pattern, $content, $matches);

$arr = array();

for ($i=0; $i<count($matches); $i++){
    $arr[$matches[1][$i]] = $matches[2][$i];    
}

/* This is an example on how to use it */
echo "Location: " . $arr["Location"] . "<br><br>";

/* This is the array */
print_r($arr);

?>

If your array has a lot of elements dont use the count() function in the for loop, calculate the value first and then use it as a constant.

Upvotes: 1

nush
nush

Reputation: 142

I'm using your $content variable:

$preg1 = preg_match_all('#<name>([^<]+)#', $content, $name_arr);
$preg2 = preg_match_all('#<value>([^<]+)#', $content, $val_arr);
$array = array_combine($name_arr[1], $val_arr[1]);

Upvotes: 3

ircmaxell
ircmaxell

Reputation: 165261

First of all, never use regex to parse xml...

You could do this with an XPATH query...

First, wrap the content in a root tag to make the parser happy (if it doesn't already have it):

$content = '<root>' . $content . '</root>';

Then, load the document

$dom = new DomDocument();
$dom->loadXml($content);

Then, initialize the XPATH

$xpath = new DomXpath($dom);

Write your query:

$xpathQuery = '//name[text()="Manufacturer"]/follwing-sibling::value/text()';

Then, execute it:

$manufacturer = $xpath->evaluate($xpathQuery);

If I did the xpath right, it $manufacturer should be John Deere...

You can see the docs on DomXpath, a basic primer on XPath, and a bunch of XPath examples...

Edit: That won't work (PHP doesn't support that syntax (following-sibling). You could do this instead of the xpath query:

$xpathQuery = '//name[text()="Manufacturer"]';
$elements = $xpath->query($xpathQuery);
$manufacturer = $elements->item(0)->nextSibling->nodeValue;

Upvotes: 1

Ed Mazur
Ed Mazur

Reputation: 3112

Using XMLReader:

$content = '<name>Manufacturer</name><value>John Deere</value><name>Year</name><value>2001</value><name>Location</name><value>NSW</value><name>Hours</name><value>6320</value>';
$content = '<content>' . $content . '</content>';
$output = array();

$reader = new XMLReader();
$reader->XML($content);
$currentKey = null;
$currentValue = null;
while ($reader->read()) {
    switch ($reader->name) {
        case 'name':
            $reader->read();
            $currentKey = $reader->value;
            $reader->read();
            break;
        case 'value':
            $reader->read();
            $currentValue = $reader->value;
            $reader->read();
            break;
    }
    if (isset($currentKey) && isset($currentValue)) {
        $output[$currentKey] = $currentValue;
        $currentKey = null;
        $currentValue = null;
    }
}

print_r($output);

The output is:

Array
(
    [Manufacturer] => John Deere
    [Year] => 2001
    [Location] => NSW
    [Hours] => 6320
)

Upvotes: 0

palswim
palswim

Reputation: 12140

I'll edit as my PHP is wrong, but here's some PHP (pseudo-)code to give some direction.

$pattern = '|<name>([^<]*)</name>\s*<value>([^<]*)</value>|'
preg_match_all($pattern, $content, $matches, PREG_SET_ORDER);
for($i = 0; $i < count($matches); $i++) {
    $arr[$matches[$i][1]] = $matches[$i][2];
}

$arr is the array you want to store the name/value pairs.

Upvotes: 0

sberry
sberry

Reputation: 132088

You don't want to use regex for this. Try out something like SimpleXML

EDIT
Well, why don't you start with this:

<?php

$content = "<root>" . $content . "</root>";
$xml = new SimpleXMLElement($c);
print_r($xml);

?>

EDIT 2
Despite the fact that some of the answers posted using regular expression MAY work, you should get in the habit of using the correct tool for the job and regular expressions are not the correct tool for parsing of XML.

Upvotes: 5

rubber boots
rubber boots

Reputation: 15204

This is rather simple, can be solved by regex. Should be:

$name  = '<name>\s*([^<]+)</name>\s*';
$value = '<value>\s*([^<]+)</value>\s*';

$pattern = "|$name $value|";
preg_match_all($pattern, $content, $matches);

# create hash
$stuff = array_combine($matches[1], $matches[2]);

# display
var_dump($stuff);

Regards

rbo

Upvotes: 2

Related Questions