【问题标题】:Check if child exists? - SimpleXML (PHP)检查孩子是否存在? - SimpleXML (PHP)
【发布时间】:2017-02-24 11:38:43
【问题描述】:

我有不同的 XML 文件,我为每个 XML 文件重命名了所有单独的标签,这样每个 XML 文件都具有相同的标签名称。这很容易,因为该函数是为 XML 文件定制的。

除了为每个 XML 文件编写 7 个新函数之外,我现在想检查 XML 文件是否有指定的子文件。因为如果我想说:

foreach ($items as $item) {
$node = dom_import_simplexml($item);
$title = $node->getElementsByTagName('title')->item(0)->textContent;
$price = $node->getElementsByTagName('price')->item(0)->textContent;
$url = $node->getElementsByTagName('url')->item(0)->textContent;
$publisher = $node->getElementsByTagName('publisher')->item(0)->textContent;
$category = $node->getElementsByTagName('category')->item(0)->textContent;
$platform = $node->getElementsByTagName('platform')->item(0)->textContent;
}

我有时会收到:PHP Notice: Trying to get property of non-object in ...

例如。两个不同的 XML 表。一个包含发布者、类别和平台,另一个不包含:

XML 1:

<products>
  <product>
    <desc>This is a Test</desc>
    <price>11.69</price>
    <price_base>12.99</price_base>
    <publisher>Stackoverflow</publisher>
    <category>PHP</category>
    </packshot>
    <title>Check if child exists? - SimpleXML (PHP)</title>
    <url>http://stackoverflow.com/questions/ask</url>
  </product>
</products>

XML 2:

<products>
  <product>
   <image></image>
    <title>Questions</title>
    <price>23,90</price>
    <url>google.de/url>
    <platform>Stackoverflow</platform>
  </product>
</products>

您会看到,有时一个 XML 文件包含发布者、类别和平台,但有时不包含。 但也可能不是 XML 文件的每个节点都包含第一个中的所有属性!

因此,如果节点包含发布者、类别或/和平台,我需要检查单个 XML 文件的每个节点。

如何使用 SimpleXML 做到这一点? 我考虑过 switch case,但首先我需要检查每个节点中包含哪些子节点。

编辑: 也许我找到了解决方案。这是一个解决方案吗?

if($node->getElementsByTagName('platform')->item(0)){
        echo $node->getElementsByTagName('platform')->item(0)->textContent . "\n";
    }

您好,谢谢!

【问题讨论】:

  • 您可以通过if(isset($node-&gt;getElementsByTagName('publisher')-&gt;item))if(is_array($node-&gt;getElementsByTagName('publisher')-&gt;item)) 进行验证
  • 但是你应该直接使用simplexml
  • But you should use simplexml directly.是什么意思
  • 看看我的编辑。你认为这是一个解决方案。还是?

标签: php xml simplexml


【解决方案1】:

通往罗马的一种方式...(工作示例)

$xml = "<products>
  <product>
    <desc>This is a Test</desc>
    <price>11.69</price>
    <price_base>12.99</price_base>
    <publisher>Stackoverflow</publisher>
    <category>PHP</category>
    <title>Check if child exists? - SimpleXML (PHP)</title>
    <url>http://stackoverflow.com/questions/ask</url>
  </product>
</products>";
$xml = simplexml_load_string($xml);
#set fields to look for
foreach(['desc','title','price','publisher','category','platform','image','whatever'] as $path){
       #get the first node
       $result = $xml->xpath("product/{$path}[1]");
       #validate and set
       $coll[$path] = $result?(string)$result[0]:null;  
       #if you need here a local variable do (2 x $)
       ${$path} = $coll[$path];
}
#here i do array_filter() to remove all NULL entries
print_r(array_filter($coll));
#if local variables needed do
extract($coll);#this creates $desc, $price

注意&lt;/packshot&gt; 是一个无效节点,在此处删除。

xpath 语法https://www.w3schools.com/xmL/xpath_syntax.asp

【讨论】:

  • 路径应该是$xml-&gt;xpath("products/product/{$path}[1]");。还是我错了?
  • @Jan 它是关于绝对的相对论。绝对是/a/b/c 相对是b/cc 都将在这里找到相同的数据。仅当您拥有子节点通常相同的 komplex xml 时,请注意,您最好使用绝对路径而不是相对路径一次。
  • 我没有得到你的代码。经过1小时的尝试,我可能找到了解决方案。我更新了我的问题,这也是一个解决方案。
【解决方案2】:

首先,通过使用dom_import_simplexml 从 SimpleXML 切换到 DOM,您的代码过于复杂。用 DOM 做的事情可以用 SimpleXML 用更短的代码来完成。

而不是这个:

$node = dom_import_simplexml($item);
$title = $node->getElementsByTagName('title')->item(0)->textContent;

你可以使用:

$title = (string)$item->title[0];

甚至只是:

$title = (string)$item->title;

要了解为什么会这样,请查看the SimpleXML examples in the manual

有了这些知识,您会惊讶于查看孩子是否存在是多么简单:

if ( isset($item->title) ) {
    $title = (string)$item->title;
} else {
    echo "There is no title!";
}

【讨论】:

    猜你喜欢
    • 2010-12-06
    • 2017-10-24
    • 2016-09-18
    • 2011-11-25
    • 2016-09-20
    • 2013-05-09
    • 2017-02-25
    • 1970-01-01
    • 2017-04-27
    相关资源
    最近更新 更多