php associative arrays, regex, array

2019-06-14 08:17发布

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];

7条回答
孤傲高冷的网名
2楼-- · 2019-06-14 08:42

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;
查看更多
Lonely孤独者°
3楼-- · 2019-06-14 08:45

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
)
查看更多
仙女界的扛把子
4楼-- · 2019-06-14 09:00

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.

查看更多
爷的心禁止访问
5楼-- · 2019-06-14 09:00

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.

查看更多
趁早两清
6楼-- · 2019-06-14 09:01

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

查看更多
爱情/是我丢掉的垃圾
7楼-- · 2019-06-14 09:05

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]);
查看更多
登录 后发表回答