我有一个大的XML文件,看起来像这样:
<envelope>
<headers>
...
</headers>
<data>
<Channel Id="303131" created="2016-06-02T14:01:00" modified="2016-06-02T14:01:00">
<Fields />
<Links>
<ChannelNodes type="ChannelChannelNodes">
*** <ChannelNode Id="318630" created="2016-07-15T14:44:00" modified="2016-07-15T14:44:00" Index="0" LinkId="338254">
<Fields />
<Links>
<ChannelNodes type="ChannelNodeChannelNodes">
*** <ChannelNode Id="303152" created="2016-06-02T14:29:00" modified="2016-08-31T11:14:00" Index="0" LinkId="338256">
<Fields />
<Links>
<ChannelNodes type="ChannelNodeChannelNodes">
<ChannelNode Id="303155" created="2016-06-02T14:29:00" modified="2016-07-08T09:50:00" Index="0" LinkId="311083">
<Fields />
<Links>
<ChannelNodes type="ChannelNodeChannelNodes">
*** <ChannelNode Id="303157" created="2016-06-02T14:29:00" modified="2016-08-26T14:08:00" Index="0" LinkId="311086">
<Fields />
<Links>
<ChannelNodes type="ChannelNodeChannelNodes">
<ChannelNode Id="303158" created="2016-06-02T14:29:00" modified="2016-08-26T14:09:00" Index="0" LinkId="311087">
<Fields />
<Links />
</ChannelNode>
*** <ChannelNode Id="303159" created="2016-06-02T14:30:00" modified="2016-08-26T14:09:00" Index="1" LinkId="311088">
<Fields />
<Links />
</ChannelNode>
<ChannelNode Id="303160" created="2016-06-02T14:30:00" modified="2016-08-26T14:09:00" Index="2" LinkId="311089">
<Fields />
<Links />
</ChannelNode>
</ChannelNodes>
</Links>
</ChannelNode>
<ChannelNode Id="303161" created="2016-06-02T14:30:00" modified="2016-08-26T14:09:00" Index="1" LinkId="311090">
<Fields />
<Links />
</ChannelNode>
<ChannelNode Id="303162" created="2016-06-02T14:30:00" modified="2016-08-26T14:10:00" Index="2" LinkId="311091">
<Fields />
<Links />
</ChannelNode>
...etc
我需要找到一种方法来列出给定id的所有祖先节点的ID(我不确定我是否使用了正确的术语)。例如。我的输入可能是$ id = 303159,我的输出应该是$ ids = [303157,303152,318630](所有相关的行标有***)。
很可能输入id可以在不同深度的同一xml文件中的不同位置找到。例如,在上面的示例中,输入id有三个祖先,但它可能在一个地方有1个祖先,在同一个文件中有另一个地方有4个祖先。但是我需要的输出只是一个所有祖先的数组(1个祖先+ 4个祖先会产生5个元素的数组)。
我想我可以这样做:
$arr = simplexml_load_string($xml, null, LIBXML_NOCDATA);
只需使用许多foreach语句,搜索正确的ID。 问题在于它感觉不对,因为我确定还有另一种方法可以做到这一点,因为xml的深度可以随时改变(现在最深层是4个节点,但它可能是8个节点)在将来或任何其他数字)。
修改
这是我目前的解决方案。它适用于我当前的数据,但它不是一个好的解决方案。
$arr = simplexml_load_string($xml, null, LIBXML_NOCDATA);
foreach($arr->data->Channel as $cn1) {
$result[(string) $cn1->attributes()] = "allt";
foreach ($cn1->Links->ChannelNodes->ChannelNode as $cn2) {
$result[(string) $cn2->attributes()][] = (string) $cn1->attributes();
foreach ($cn2->Links->ChannelNodes->ChannelNode as $cn3) {
$result[(string) $cn3->attributes()][] = (string) $cn1->attributes();
$result[(string) $cn3->attributes()][] = (string) $cn2->attributes();
foreach ($cn3->Links->ChannelNodes->ChannelNode as $cn4) {
$result[(string) $cn4->attributes()][] = (string) $cn1->attributes();
$result[(string) $cn4->attributes()][] = (string) $cn2->attributes();
$result[(string) $cn4->attributes()][] = (string) $cn3->attributes();
foreach ($cn4->Links->ChannelNodes->ChannelNode as $cn5) {
$result[(string) $cn5->attributes()][] = (string) $cn1->attributes();
$result[(string) $cn5->attributes()][] = (string) $cn2->attributes();
$result[(string) $cn5->attributes()][] = (string) $cn3->attributes();
$result[(string) $cn5->attributes()][] = (string) $cn4->attributes();
foreach ($cn5->Links->ChannelNodes->ChannelNode as $cn6) {
$result[(string) $cn6->attributes()][] = (string) $cn1->attributes();
$result[(string) $cn6->attributes()][] = (string) $cn2->attributes();
$result[(string) $cn6->attributes()][] = (string) $cn3->attributes();
$result[(string) $cn6->attributes()][] = (string) $cn4->attributes();
$result[(string) $cn6->attributes()][] = (string) $cn5->attributes();
foreach ($cn6->Links->ChannelNodes->ChannelNode as $cn7) {
$result[(string) $cn7->attributes()][] = (string) $cn1->attributes();
$result[(string) $cn7->attributes()][] = (string) $cn2->attributes();
$result[(string) $cn7->attributes()][] = (string) $cn3->attributes();
$result[(string) $cn7->attributes()][] = (string) $cn4->attributes();
$result[(string) $cn7->attributes()][] = (string) $cn5->attributes();
$result[(string) $cn7->attributes()][] = (string) $cn6->attributes();
}
}
}
}
}
}
}
答案 0 :(得分:0)
您只需要一个反向路径xpath查询。
$lookForID = 303159;
$sXML = simplexml_load_string($xml, null, LIBXML_NOCDATA);
$ancestorIdNodes = $sXML->xpath(
"//ChannelNode[@Id=\"{$lookForID}\"]/ancestor::ChannelNode/@Id"
);
$ancestorIds = [];
foreach($ancestorIdNodes as $node) {
$ancestorIds[] = (string) $node['Id'];
}
// $ancestorIds is an array of IDs you are looking for.
实际的xpath字符串可以读作:获取任何ChannelNode元素的Id属性,这些元素是树中Id属性等于303159的任何ChannelNode的祖先。