1

I am writing a script to handle jsonp response. So that I can interpret it, send it to client, and use my own callback in ajax. Anyway, the response from server is json if it is successful. If the request fails, it returns an xml.

I checked some answers before.

Check whether returned file is XML or not

How check if a String is a Valid XML with-out Displaying a Warning in PHP

This answer works fine, my bad.

I write this.

$xml = simplexml_load_string($result,'SimpleXmlElement', LIBXML_NOERROR+LIBXML_ERR_FATAL+LIBXML_ERR_NONE); if(!$xml){// json} 

This gives out warning,

node no longer exist

The warning enters the json response, making it hard to parse.

I know if I suppress the warnings in php, it would work fine, but this is not the answer I want. I want to know, how do I check the string format, without giving out warning. Even in developing environment. I think it's better to solve problem from the root.

Then I used this,

$xml = simplexml_load_string($result,'SimpleXmlElement', LIBXML_NOERROR+LIBXML_ERR_FATAL+LIBXML_ERR_NONE); if($xml == false){ // json } 

This enters the block no matter if the string is xml or json. $xml == false is always evaluated as true.

I think if you can explain to me, the difference between $xml == false and !$xml that would be great. Thanks in advance.

6
  • Why not just send a different content-type header to send the string? If it's invalid use text/plain and if it's valid use application/xml or whatever you need. Then based on the content-type header, either parse the XML or display the error. Commented Mar 11, 2014 at 3:16
  • Thanks @Mike, but where are you suggesting me to do the checking? Commented Mar 11, 2014 at 3:29
  • Possible duplicate of stackoverflow.com/questions/4554233/…. Commented Mar 11, 2014 at 3:42
  • @TwoWholeWorms no man, this is not a duplicate. In fact, I have the link in my question. Commented Mar 11, 2014 at 3:58
  • Well, the answer you don't want is the answer to your problem, as there is no other way to do it without using the iterative code I've linked below, which is a hell of a lot more inefficient. Sorry, mate. Commented Mar 11, 2014 at 4:01

1 Answer 1

3

Since a way to detect XML without parsing it has been asked for, the following regex should match a valid XML string, at least preliminarily:

^(<([a-zA-Z0-9]+)([\s]+[a-zA-Z0-9]+="[a-zA-Z0-9]+")*>([^<]*([^<]*|(?1))[^<]*)*<\/\2>)$ 

This can be tested here: http://regex101.com/r/mW9aZ5

However, I still assert that the libxml way is better. :)

-- Edit 1

Turns out this is a duplicate of: How check if a String is a Valid XML with-out Displaying a Warning in PHP

Tjirp's answer in that thread using libxml_use_internal_errors(true); is much more efficient. I suggest using that.

-- My original answer, which is inefficient

Edit: This requires iterating through every node in the XML tree calling ->isValid() for each node. ->isValid() ONLY checks the current node. It does not check the entire tree at once, as one would expect. It's also worth noting that the documentation on PHP.net is ambiguous and lacking complete useful usage examples. I've left this here rather than removing it for this reason.

You can use XMLReader::isValid() to validate that an opened XML file or string actually contains valid XML.

To load from the $result string itself:

$xml = new XMLReader(); $xml->xml($result); $xml->setParserProperty(XMLReader::VALIDATE, true); $success = true; while ($xml->read()) { if (!$xml->isValid()) { $success = false; } } if ($success) { // Return valid response } else { // Return invalid response } 

Alternatively, you can also load the XML from from a file on the filesystem:

$xml = new XMLReader(); $xml->open($file); // Rest of code as above 

Regarding if ($xml == false) always evaluating to true, this should never happen unless $xml is always false. Are you sure you didn't unintentionally write if ($xml = false) instead by accident?

Sign up to request clarification or add additional context in comments.

5 Comments

Sorry, i tried it, but why is even an arbitrary plain text string is regarded as valid?
That is a bloody good question, and I'm now looking into it for you. :/
You work hard, I hope I can accept your answer. But the problem is not solved. As I stated, I if $xml is not valid, it is in jsonp format. Warning is given on XMLRreader::read(). My problem is here, if the string is definitely not xml. I am not saying xml with wrong format, but definitely OTHER format. Your answer would work fine with invalid xml. But if I feed other format, they give more warnings.
Well, as a horrible hack, if (!preg_match('/^\s*</', $result)) will at least tell you if it starts with a < (and some optional whitespace characters). However, I still think the answer given in the post you linked to is still your best bet, especially considering what you've just mentioned.
The hack works. Though ugly. The link you mentioned works. The first time tried it, i made some mistakes. Thanks a lot. If you update what you just said to you answer, I would accept it as the best answer. Thanks a lot.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.