2013-07-08 93 views
4

这是我的XML(片段):遍历XML树来获得属性值

<?xml version="1.0" encoding="utf-8"?> 
<test> 
    <body label_position="left"> 
    <page number="1"> 
     <itemset name=""> 
     <item name="" id="1" /> 
     <item name="" id="2" label_position="right" /> 
    </itemset> 
    </page> 
    </body> 
</test> 

我想做到:
是否<item id="1">label_position属性设置?
(1)如果是,请将其退回。
(2)如果没有,请检查节点的父节点是否属于该属性。 (3)如果父母具有该属性,则返回该属性。
(4)如果不是,则转到步骤(2)。 <body>是要检查的“最旧”节点。

我已经试过什么:
我使用simplexmlxpath,我试图选择<item>及其所有祖先,然后向上遍历树并与label_position第一次出现停止。

$xml->xpath("//item[@id='1']::ancestors-or-self/@label_position"); 

产生了invalid expression

(1)如何获得此表达式的工作方式?
(2)这可以通过“xpath-only”完成 - 无需遍历树并执行搜索?

编辑:感谢choroba & dirkk,我可以把它在一起:

$test = (string)array_reverse($xml->xpath("//item[@id='2']/ancestor-or-self::*/@label_position"))[0]; 

说明:如果两个<item><body>具有属性,xpath将返回这两个值的数组,第一个是<body>。在这种情况下,我想先获得<item>,这就是为什么array_reverse()

看到它的工作:http://codepad.viper-7.com/jDPIde

回答

2

你应该更加小心的XPath语法。你表达的正确形式是

//item[@id='1']/ancestor-or-self::*/@label_position 

谓词后,您不能使用::,和你有一个轴后指定::

+0

谢谢,作品像一个魅力! – michi

2

您的XPath无效。轴步骤必须位于元素名称的前面,例如类似axis::node,而不是其他方式。

以下应该工作。你的逻辑已经是xpath-only,遍历树是完全正确的。

(//item[@id='1']/ancestor-or-self::*/@label_position)[last()] 
+0

虽然'/ data()'产生了一个“无效表达式”,但没有它,它就像一个魅力。谢谢! – michi

+0

@michi我更新了我的XPath以反映编辑中的更改。你可以单独使用XPath来完成,不需要使用'array_reverse' – dirkk

+0

真的很棒!确实需要额外的行才能转换为字符串,但请参阅http://codepad.viper-7.com/NflXLz – michi