按标签名称同时获取两个值?

时间:2017-02-15 16:42:34

标签: php xml dom

我有几个XML文件,想要获得每个产品的两个值。我可以这样做:

$doc = simplexml_import_dom($dom);
$items = $doc->xpath("//$tagName");

$titles = array();
$prices = array();

foreach ($items as $item) {
    $node = dom_import_simplexml($item);

    if(strcasecmp($tagName, "title") == 0){
        array_push($titles, $node->textContent);
    }

    if(strcasecmp($tagName, "price") == 0){
        array_push($prices, $node->textContent);
    }
}

但我认为这种方式太不稳定了。我希望两个价值形成一对是安全的。因为它可能是一个产品不包含价格或标题,这是不可想象的,但它可能是! (文件不是来自我!

那么有没有办法同时获得每个name的{​​{1}}和preis代码? - 因为这是唯一安全的方法!

问候,谢谢!

2 个答案:

答案 0 :(得分:1)

一项建议是使用DOM代替simplexml。我觉得它更有表现力。

---后来编辑---

这是simplexml实现

$string = <<<EOS
<?xml version='1.0' encoding='UTF-8'?>
<products>
  <product>
    <name>Battlefield 1</name>
    <preis>80</preis>
    <sterne>3</sterne>
    <desc>Dies ist ein Text</desc>
    <link>https://www.google.de/</link>
  </product>
  <product>
    <name>Battlefield 2</name>
    <preis>180</preis>
    <sterne>3</sterne>
    <desc>Dies ist ein Text</desc>
    <link>https://www.google.de/</link>
  </product>
  <product>
    <name>Battlefield 3</name>
    <preis>280</preis>
    <sterne>3</sterne>
    <desc>Dies ist ein Text</desc>
    <link>https://www.google.de/</link>
  </product>
  <product>
    <name>Battlefield 4</name>
    <preis>380</preis>
    <sterne>3</sterne>
    <desc>Dies ist ein Text</desc>
    <link>https://www.google.de/</link>
  </product>
  <product>
    <name>Battlefield 5</name>
    <preis>480</preis>
    <sterne>3</sterne>
    <desc>Dies ist ein Text</desc>
    <link>https://www.google.de/</link>
  </product>
</products>
EOS;

$doc = simplexml_load_string($string);

// get a list of products
$products = $doc->xpath('/products/product');

// iterate of the list
foreach ($products as $product) {
    $name = $product->name->__toString();
    $price = $product->preis->__toString();

    echo $name . ' = ' . $price . PHP_EOL;
}

---后期编辑结束---

这是一个有效的例子:

<?php

$string = <<<EOS
<?xml version='1.0' encoding='UTF-8'?>
<products>
  <product>
    <name>Battlefield 1</name>
    <preis>80</preis>
    <sterne>3</sterne>
    <desc>Dies ist ein Text</desc>
    <link>https://www.google.de/</link>
  </product>
  <product>
    <name>Battlefield 2</name>
    <preis>180</preis>
    <sterne>3</sterne>
    <desc>Dies ist ein Text</desc>
    <link>https://www.google.de/</link>
  </product>
  <product>
    <name>Battlefield 3</name>
    <preis>280</preis>
    <sterne>3</sterne>
    <desc>Dies ist ein Text</desc>
    <link>https://www.google.de/</link>
  </product>
  <product>
    <name>Battlefield 4</name>
    <preis>380</preis>
    <sterne>3</sterne>
    <desc>Dies ist ein Text</desc>
    <link>https://www.google.de/</link>
  </product>
  <product>
    <name>Battlefield 5</name>
    <preis>480</preis>
    <sterne>3</sterne>
    <desc>Dies ist ein Text</desc>
    <link>https://www.google.de/</link>
  </product>
</products>
EOS;

$doc = new DOMDocument();
$doc->loadXml($string);
$products = $doc->getElementsByTagName('product');

$index = 0;
foreach ($products as $product) {
    echo 'Showing information for product #' . $index++ . PHP_EOL;
    foreach ($product->childNodes as $property) {
        if ($property instanceof DOMText) continue;
        echo ' ->' . $property->localName . ' = ' . $property->textContent . PHP_EOL;
    }
}

如果您需要simplexml

,请告诉我们

答案 1 :(得分:1)

是的,这是。您正在将DOM转换为SimpleXML以使用Xpath。这不是必需的。 DOM具有DOMXpath类,DOMXpath::evaluate()SimpleXMLElement::xpath()更强大。

Xpath可以做很多事情。例如,您可以获取具有namepreis的任何产品:

//product[normalize-string(name) != '' and normalize-string(preis) != '']

但要获得连接的值,您需要获取并迭代product个节点,然后执行其他Xpath表达式来获取值。

$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);

$result = [];
foreach ($xpath->evaluate('//product') as $product) {
  $result[] = [
    'title' => $xpath->evaluate('string(name)', $product),
    'price' => $xpath->evaluate('number(preis)', $product)
  ];
}

var_dump($result);

输出:

array(5) {
  [0]=>
  array(2) {
    ["title"]=>
    string(13) "Battlefield 1"
    ["price"]=>
    float(80)
  }
  [1]=>
  array(2) {
    ["title"]=>
    string(13) "Battlefield 2"
    ["price"]=>
    float(180)
  }
  ...

string(name)获取所有name子节点并将结果转换为字符串。在Xpath中,表示返回列表中第一个节点的文本内容。如果列表为空,则会得到一个空字符串。

number(preis)获取所有preis个子节点,并将第一个节点的文本内容强制转换为数字。如果此处没有匹配的节点,则结果为0