Joe
Joe

Reputation: 1055

PHP 7.2 xml domdocument get nodevalue of given childnode value of sibling having attribute equal to

I've the following xml

<ReviseInventoryStatusResponse xmlns="urn:ebay:apis:eBLBaseComponents">
  <Timestamp>2019-01-02T15:42:31.495Z</Timestamp>
  <Ack>Warning</Ack>
  <Errors>
    <ShortMessage>Requested StartPrice and Quantity revision is redundant.</ShortMessage>
    <LongMessage>The existing price and quantity values are identical to those specified in the request and, therefore, have not been modified.</LongMessage>
    <ErrorCode>21917091</ErrorCode>
    <SeverityCode>Warning</SeverityCode>
    <ErrorParameters ParamID="ItemID">
      <Value>770386906435</Value>
    </ErrorParameters>
    <ErrorParameters ParamID="SKU">
      <Value/>
    </ErrorParameters>
    <ErrorClassification>RequestError</ErrorClassification>
  </Errors>
  <Errors>
    <ShortMessage>Requested StartPrice and Quantity revision is redundant.</ShortMessage>
    <LongMessage>The existing price and quantity values are identical to those specified in the request and, therefore, have not been modified.</LongMessage>
    <ErrorCode>21917091</ErrorCode>
    <SeverityCode>Warning</SeverityCode>
    <ErrorParameters ParamID="ItemID">
      <Value>770386906436</Value>
    </ErrorParameters>
    <ErrorParameters ParamID="SKU">
      <Value/>
    </ErrorParameters>
    <ErrorClassification>RequestError</ErrorClassification>
  </Errors>
  ...
  </ReviseInventoryStatusResponse>

I need to get the ShortMessage for the given ItemID that is found in ErrorParameters/Value where ParamID="ItemID"

I've been able to check if a node with the given value exists:

$xmlr = new DOMDocument();
$xmlr->load('ReviseInventoryStatusResponse_error.xml');
$xpath = new DOMXPath($xmlr);
$xpath->registerNamespace('e', 'urn:ebay:apis:eBLBaseComponents');
$nodeExists=($xpath->query('//e:ErrorParameters[@ParamID="ItemID"]/e:Value[. = "770386906435"]')->length>0)?1:0;

then I tried to get its ShortMessage with

$xpath->query('//e:Errors[e:ErrorParameters@ParamID="ItemID"]/e:Value[.="770386906435"]/e:ShortMessage')

but got invalid predicate as expected since not find the right way to combine filters.

can pls suggest the right way?

Thanks

Upvotes: 0

Views: 72

Answers (2)

Nigel Ren
Nigel Ren

Reputation: 57121

If you use the XPath to fetch the short message, a quick way to check if there is a message is to just check if there are any results from the query...

$smgs = $xpath->query('//e:Errors[e:ErrorParameters[@ParamID="ItemID" and e:Value="7720386906435"]]/e:ShortMessage');
if ( count($smgs) > 0 ) {
    echo $smgs[0]->nodeValue;
}
else {
    echo "does not exist";
}

Upvotes: 1

ThW
ThW

Reputation: 19482

Here are several ways

  1. Select the Errors element node using nested conditions:
    //e:Errors[e:ErrorParameters[@ParamID="ItemID"]/e:Value[. = "770386906435"]]/e:ShortMessage
  2. Select the Value element and use the parent axis
    //e:ErrorParameters[@ParamID="ItemID"]/e:Value[. = "770386906435"]/parent::*/parent::*/e:ShortMessage
  3. Select the Value element and use the ancestor axis
    //e:ErrorParameters[@ParamID="ItemID"]/e:Value[. = "770386906435"]/ancestor::e:Errors/e:ShortMessage

If you use DOMXpath::evaluate() you can use count() and string() to fetch the scalar values directly. You might not even need to check if the node exists, because the result will be an empty string in this case.

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXPath($document);
$xpath->registerNamespace('e', 'urn:ebay:apis:eBLBaseComponents');
$nodeExists = $xpath->evaluate(
  'count(//e:ErrorParameters[@ParamID="ItemID"]/e:Value[. = "770386906435"]) > 0'
);

var_dump($nodeExists);

$shortMessage = $xpath->evaluate(
  'string(//e:Errors[e:ErrorParameters[@ParamID="ItemID"]/e:Value[. = "770386906435"]]/e:ShortMessage)'
);
var_dump($shortMessage);

$shortMessage = $xpath->evaluate(
  'string(//e:ErrorParameters[@ParamID="ItemID"]/e:Value[. = "770386906435"]/parent::*/parent::*/e:ShortMessage)'
);
var_dump($shortMessage);

$shortMessage = $xpath->evaluate(
  'string(//e:ErrorParameters[@ParamID="ItemID"]/e:Value[. = "770386906435"]/ancestor::e:Errors/e:ShortMessage)'
);
var_dump($shortMessage);

Output:

bool(true) 
string(56) "Requested StartPrice and Quantity revision is redundant." 
string(56) "Requested StartPrice and Quantity revision is redundant." 
string(56) "Requested StartPrice and Quantity revision is redundant."

Upvotes: 2

Related Questions