按父节点属性选择XML节点


select XML nodes by parent node attribute

通过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>";
   }
?>

这将向我返回结果的Subject部分中的所有AttributeValue结果。如何将条件条件条件添加到foreach循环中,使其仅返回AttributeId="urn:Cisco:uc:1.0:callingnumber处的结果?

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

直接从我警告外星人的答案(我认为这是解决这个问题的最佳方法)开始,您可以使用非常类似的代码方法,使用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;