2017-02-24 111 views
1

我有不同的XML文件,我为每个XML文件重命名所有单独的标记,以便每个XML文件具有相同的标记名称。这很简单,因为该功能是为XML文件定制的。检查孩子是否存在? - SimpleXML(PHP)

但是为每个XML文件编写7个新函数的例子现在我想检查一个XML文件是否有specidifed子节点。因为如果我想说:

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做到这一点? 我考虑过开关盒,但起初我需要检查每个节点中包含哪些孩子。

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

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

问候和谢谢你!

+0

你可以做'如果(isset($节点 - >的getElementsByTagName('出版商:

武装与知识,你会发现它是多么简单,看是否有孩子存在与否惊讶') - > item))'和'if(is_array($ node-> getElementsByTagName('publisher') - > item))'验证 – JustOnUnderMillions

+0

但您应该直接使用'simplexml'。 – JustOnUnderMillions

+0

可能重复的[php的SimpleXML检查,如果一个孩子存在](http://stackoverflow.com/questions/1560827/php-simplexml-check-if-a-child-exists) –

回答

0

一种方式来罗马...(工作示例)

$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 

</packshot>是一个无效的节点,此处被拆除。

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

+0

路径应该是'$ xml-> xpath(“products/product/{$ path} [1]”);'。或者我错了? – Jan

+0

@Jan它关于相对绝对。绝对是'/ a/b/c'相对是'b/c'或'c'都会在这里找到相同的数据。只有当你有komplex xml,其中子节点通常是相同的,那么你最好做绝对路径而不是相对一次。 – JustOnUnderMillions

+0

看看这里https://www.w3schools.com/xmL/xpath_syntax.asp – JustOnUnderMillions

0

首先,你从SimpleXML的切换到DOM与dom_import_simplexml代码过于复杂。您使用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!"; 
}