按父节点属性选择XML节点

时间:2014-10-14 21:57:37

标签: php arrays xml

我正在通过POST提供XML块。我想解析AttributeValue等于AttributeId的具体urn:Cisco:uc:1.0:callingnumber

这是我通过POST获得的数据:

<?xml version="1.0" encoding="UTF-8"?>
<Request xmlns="urn:oasis:names:tc:xacml:2.0:context:schema:os">
<Subject SubjectCategory="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
<Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:role-id"
DataType="http://www.w3.org/2001/XMLSchema#string" Issuer="requestor">
<AttributeValue>CISCO:UC:UCMPolicy</AttributeValue>
</Attribute>
<Attribute AttributeId="urn:Cisco:uc:1.0:callingnumber" DataType="http://www.w3.org/2001/XMLSchema#string">
<AttributeValue>89996203741</AttributeValue>
</Attribute>
<Attribute AttributeId="urn:Cisco:uc:1.0:callednumber"
DataType="http://www.w3.org/2001/XMLSchema#string">
<AttributeValue>95551231234</AttributeValue>
</Attribute>
<Attribute AttributeId="urn:Cisco:uc:1.0:transformedcgpn"
DataType="http://www.w3.org/2001/XMLSchema#string">
<AttributeValue>89996203741</AttributeValue>
</Attribute>
<Attribute AttributeId="urn:Cisco:uc:1.0:transformedcdpn"
DataType="http://www.w3.org/2001/XMLSchema#string">
<AttributeValue>95551231234</AttributeValue>
</Attribute>
</Subject>
<Resource>
<Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id"
DataType="http://www.w3.org/2001/XMLSchema#anyURI">
<AttributeValue>CISCO:UC:VoiceOrVideoCall</AttributeValue>
</Attribute>
</Resource>
<Action>
<Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"
DataType="http://www.w3.org/2001/XMLSchema#anyURI">
<AttributeValue>any</AttributeValue>
</Attribute>
</Action>
<Environment>
<Attribute AttributeId="urn:Cisco:uc:1.0:triggerpointtype"
DataType="http://www.w3.org/2001/XMLSchema#string">
<AttributeValue>translationpattern</AttributeValue>
</Attribute>
</Environment>
</Request>

到目前为止我做过的尝试:

<?php
$datarequest = trim(file_get_contents('php://input'));
$xmlrequest = simplexml_load_string($datarequest);
$root=$xmlrequest->Subject;


foreach($root->Attribute as $child)
   {
   echo $child->AttributeValue . "<br>";
   }
?>

这会返回结果AttributeValue部分中的所有Subject结果。如何将条件标准添加到我的foreach循环中,以便它只返回AttributeId="urn:Cisco:uc:1.0:callingnumber的结果?

2 个答案:

答案 0 :(得分:0)

SimpleXML被误导性地命名,因为(IMO)它比使用PHP DOM更复杂。这是使用DOMDocument和DOMXPath的查询实现; XPath是一种基于标签名称,值或属性查找节点的简单方法 - 更容易迭代文档并搜索子项等。

# load the XML into a new DOMDocument object
$dom = new DOMDocument;
$dom->loadXML( $xml );

# create a new DOMXPath object
$xp = new DOMXPath($dom);
# register the namespace (given in the <Request> element)
$xp->registerNamespace("o", "urn:oasis:names:tc:xacml:2.0:context:schema:os");

# search for AttributeValue nodes with parent Attribute elements 
# with that AttributeId. Note that all the node names have to be prefixed with
# the namespace
$nodes = $xp->query("//o:Attribute[@AttributeId='urn:Cisco:uc:1.0:callingnumber']/o:AttributeValue");

# go through the results and do whatever you want with them
foreach ($nodes as $n) {
    echo $n->nodeName . " node contents: " . $n->nodeValue . "\n";
}

您发布的文件的输出:

AttributeValue node contents: 89996203741

答案 1 :(得分:0)

直接来自我惊恐的外星人的答案(我觉得这是解决此问题的最佳方法),你可以使用xpath非常相似的代码方法,但仍在使用的SimpleXML。

// populate $datarequest (as per question)
$datarequest = trim(file_get_contents('php://input'));

// load the XML via SimpleXML
$xmlrequest = simplexml_load_string($datarequest);

// register the name space
$xmlrequest->registerXPathNamespace("o", "urn:oasis:names:tc:xacml:2.0:context:schema:os");

// xpath query to find a particular Attribute node that contains an AttributeId as specified in question
$xpath_result = $xmlrequest->xpath("//o:Attribute[@AttributeId='urn:Cisco:uc:1.0:callingnumber']/o:AttributeValue");

// grab the first result (xpath_result will return an array)
// and cast to a string. Alternatively, you could loop through
// the results if you're expecting more than one match
$result = '';
if (isset($xpath_result[0])) {
    $result = (string)$xpath_result[0];
}

// will output '89996203741'
print $result;