Search code examples
phpxmlxpathdomdocument

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


Solution

  • 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."