Your code is prone to xpath injection. Fix that first. The error then goes away automatically (because the xpath can not become syntactically invalid). Also you need to check/validate return values.
So you're missing the basic principles of input validation and return value validation. All you need to do is to take more care.
Input validation:
You directly inject the variable $emp_id
into the xpath string for substitution:
"//EMPLOYEES[ID='" . $emp_id . "']/EMP-NAME/text()"
However at that place you can not have a single quote inside that string. Instead check the input value (Validation) or filter/streamline it (Sanitization). For exampe, validate that it does not contain a single quote or sanitize for a numeric value. Here the second:
$expression = sprintf('//EMPLOYEES[ID="%d"]/EMP-NAME/text()', $emp_id);
$result = $xpath->evaluate($expression);
This little call to sprintf()
takes care that only numeric integer values are being used. They never contain quotes, so the expression is always valid. Invalid values that are no number will become 0
. As it's the general principle to never assign the ID 0
this should normally not cause any issue in a well designed system. If you want to do the filtering more granular please see Data Filtering in the PHP manual.
return value validation
In your code you just take over the return value of the result with very little checks (actually no checks). That is wrong. For each method or function you use you need to look it up in the PHP manual and check the documentation for all possible return values. Here the method is DOMXpath::evaluate()
, click the link and locate the Return Values section. You find this for each method and function in the PHP manual.
When you read the documentation also figure out which kind of error-handling a method makes use of. Does it throws exceptions (and if yes, which ones?) or does it show an error-condition with it's return value (like in your case)? This information is needed to decide whether to do try/catch as you did (and which is wrong because it does not throw exceptions) or if you need to check the return value:
$expression = sprintf('//EMPLOYEES[ID="%d"]/EMP-NAME/text()', $emp_id);
$result = $xpath->evaluate($expression);
if (!$result) {
throw new Exception(
sprintf('No such employee (id: %s)', var_export($emp_id, true))
);
}
This example turns a falsy return value into an exception with an individual exception message. You also might want to consider a different exception, the SPL offers some pre-defined exceptions.
I hope this answer helps you to deal with this issue and forthcoming ones.