I'm trying to validate an XML file against an XSD using the function schemaValidate(String file) from DOMDocument.
When I validate it on other tools like online validators, it works fine, but in my program I always get this error and really can't find where it's coming from:
Warning: DOMDocument::schemaValidate(/home/public_html/product/xxxx/xxxx/xxxxx/xsd/AdlSchema.xsd): failed to open stream: Permission denied in /home/public_html/xxxx/xxxx.php on line 209 Warning: DOMDocument::schemaValidate(): I/O warning : failed to load external entity "/home/public_html/product/xxxx/xxxx/xxxx/xxxx/xsd/AdlSchema.xsd" in /home/public_html/xxxx/xxxx.php on line 209 Warning: DOMDocument::schemaValidate(): Failed to locate the main schema resource at '/home/public_html/product/xxxxx/xxxxx/xxxxx/xxxx/xsd/AdlSchema.xsd'. in /home/public_html/xxxx/xxxxx.php on line 209 Warning: DOMDocument::schemaValidate(): Invalid Schema in /home/public_html/xxxx/xxxx.php on line 209
So my question is, is there a way to get more details about this error (mainly the Invalid schema one) with DOMDocument functions? and if ever someone could tell what could cause that kind of errors that would be great (xml and xsd are kind of confidentials, sorry, but once again it is working just fine with a few other tools).
Thanks!
/home/public_html/product/xxxx/xxxx/xxxxx/xsd/AdlSchema.xsd): failed to open stream: Permission deniedThe php process doesn't have the necessary rights to access the xsd file.
Let's poke around a little bit and add some debug/info code
Please add
/* debug code start. Don't forget to remove */
// if there already is a variable you use as parameter for schemaValidate() use that instead of defining a new one.
$path = '/home/public_html/product/xxxx/xxxx/xxxxx/xsd/AdlSchema.xsd';
foreach( array('file_exists', 'is_readable', 'is_writable') as $fn ) {
echo $fn, ': ', $fn($path) ? 'true':'false', "<br />\n";
}
$foo = stat($path);
echo 'mode: ', $foo['mode'], "<br />\n";
echo 'uid: ', $foo['uid'], "<br />\n";
echo 'gid: ', $foo['gid'], "<br />\n";
if ( function_exists('getmyuid') ) {
echo 'myuid: ', getmyuid(), "<br />\n";
}
if ( function_exists('getmygid') ) {
echo 'myuid: ', getmygid(), "<br />\n";
}
$foo = fopen($path, 'rb');
if ( $foo ) {
echo 'fopen succeeded';
fclose($foo);
}
else {
echo 'fopen failed';
}
/* debug code end */
right before your call to schemaValidate().
I got the same problem using relative paths to XML and XSD schema files. But after I changed it to the absolute ones the problem disappeared.
For me the reason was that the libxml entity loader was disabled (libxml_disable_entity_loader(true);). It seems to have to be enabled to use this function. I switched to DOMDocument::validateSchemaSource since I don't want to have to enable the entity loader.
Related
I'm using Simple HTML Dom to try scrape a HTML table.
I follow their instructions and have looked at many other code examples, but the file_get_html just doesn't seem to work.
Here is my code:
<?php
// Simple HTML Dom Parser
include('simple_html_dom.php');
//$worlds = ["Amera", "Antica", "Astera", "Aurera", "Aurora", "Bellona", "Belobra", "Beneva", "Calmera", "Calva", "Calvera", "Candia", "Celesta", "Chrona", "Danera", "Dolera", "Efidia", "Eldera", "Ferobra", "Fidera", "Fortera", "Garnera", "Guardia", "Harmonia", "Honera", "Hydera", "Inferna", "Iona", "Irmada", "Julera", "Justera", "Kenora", "Kronera", "Laudera", "Luminera", "Magera", "Menera", "Morta", "Mortera", "Neptera", "Nerana", "Nika", "Olympa", "Osera", "Pacera", "Premia", "Pythera", "Quilia", "Refugia", "Rowana", "Secura", "Serdebra", "Shivera", "Silvera", "Solera", "Tavara", "Thera", "Umera", "Unitera", "Veludera", "Verlana", "Xantera", "Xylana", "Yanara", "Zanera", "Zeluna"];
//foreach ($worlds as $world) {
// All HTML from the online list
$html = file_get_html('https://secure.tibia.com/community/?subtopic=worlds&world=Antica');
// Search for the online list table content
foreach ($html->find('tr[class=Table2]') as $row) {
$name = $row->find('td', 0)->plaintext;
$level = $row->find('td', 1)->plaintext;
$vocation = $row->find('td', 2)->plaintext;
echo $name . ' | ' . $level . ' | ' . $vocation . '<br>';
}
//}
?>
And I get these errors:
Warning: file_get_contents(): stream does not support seeking in D:\xampp\htdocs\simple_html_dom.php on line 76
Warning: file_get_contents(): Failed to seek to position -1 in the stream in D:\xampp\htdocs\simple_html_dom.php on line 76
Fatal error: Uncaught Error: Call to a member function find() on boolean in D:\xampp\htdocs\index.php:13 Stack trace: #0 {main} thrown in D:\xampp\htdocs\index.php on line 13
What am I doing wrong?
The table I am trying to scrape is the "Players Online" table on:
https://secure.tibia.com/community/?subtopic=worlds&world=Antica
Try this:
$html = str_get_html(file_get_contents($url));
This is a simple_html_dom library problem with the latest versions of PHP.
To correct it, simply change "$offset = -1," to "$offset = 0," in the parameters of the "file_get_html" function in the "simple_html_dom.php" file.
I don't know much about simpledom but i think you might need to use a more robust library like https://github.com/FriendsOfPHP/Goutte
I am submitting a URL request to a RESTful webservice. When I submit a variable in the url e.g "NGF and trkA", I am able to retrieve an XML responses from the remote server. However, when I input "NGF/trkA", my request fails. I really do not understand why as I have used rawurlendcode(). See the code below:
<?php
/*After pdf parsing, the result is contained in $fullText.*/
$fullText="NGF/TrkA*";
/*Remove line breaks.*/
$fullText_clean = str_replace("\n", " ", $fullText);
/*Excise the first 2 sentences of $fullText_clean (or 100 characters).*/
$truncated = substr($fullText_clean,0);
// Properly encode $truncated.
$truncated_encode = rawurlencode($truncated);
// Plug this variable, $truncated_encode, into the search url.
$xml = 'http://www.ebi.ac.uk/europepmc/webservices/rest/search/query='.$truncated_encode.'&resulttype=core';
// Return SimpleXMLElement object
$xmlObject = simplexml_load_file($xml);
if($xmlObject){
//Return information within the desired tag(s).
$title = $xmlObject->resultList->result[0]->title;
echo $fullText."<br />".
$fullText_clean."<br />".
$truncated."<br />".
$truncated_encode."<br />".
$title;
/*echo $title."<br />".$truncated;*/
}else{
echo "Failed to retreive SimpleXMLElement object.";
}
?>
This is the error that I get when $fullText="NGF/trkA":
Warning: simplexml_load_file(): I/O warning : failed to load external entity "http://www.ebi.ac.uk/europepmc/webservices/rest/search/query=NGF%2FTrkA%2A&result type=core" in /Applications/XAMPP/xamppfiles/htdocs/Lifescieco_pdfUpload/puttingitTogether.php on line 21
Failed to retreive SimpleXMLElement object.
I am writing a program to extract a comment from the bug. So first using XML-RPC I am trying to connect to Bugzilla and do it via
putting http://bugzilla.yourdomainname.com/xmlrcp.cgi
So here is my code....
setCookieJar();
$oClient->setHttpClient($oHttpClient);
$aResponse = $oClient->call('User.login', array(array(
'login'=>'username',
'password' => 'password',
'remember' => 1
)));
//Log into bugzilla.
function getInfoBug(int $bugno)
{
$aResponse = $oClient->call('Bug.get($bugno)');
//this would just return bug no.
$aResponse = $oClient->call('Bug.get( ids => [$bugno], include_fields => [\'id\', \'comments\'] )');
//Getting info about bugs.
$final = $Client->call('Bug.get(comments($aResponse)');
//
return $final;
}
$bug = 1379;
echo $answer = getInfoBug($bug);
?>
So actually am not really sure if I am calling the function correctly from the Buzilla API and another problem that is coming is that
Warning: require_once(Zend/Loader/Autoloader.php) [function.require-once]: failed to open stream: No such file or directory in C:\Zend\Apache2\htdocs\Aakash\bugzilla.php on line 6
Fatal error: require_once() [function.require]: Failed opening required 'Zend/Loader/Autoloader.php' (include_path='/usr/share/php/libzend-framework-php') in C:\Zend\Apache2\htdocs\Aakash\bugzilla.php on line 6
So am not really sure what is happening. Am just a beginner in PHP.
Check to see that Zend/Loader/Autoloader.php exists in the PHP include directory and that the permissions are set correctly for the user that your PHP script is being runas.
I have the following code...
<?php
include("lib/xmlrpc.inc");
$email='whatever#hotmail.com';
$c=new xmlrpc_client("/register/index.php", "ws.myserver.com", 80);
$f=new xmlrpcmsg('existsEmail', array(new xmlrpcval($email, "base64")));
print "<pre>" . htmlentities($f->serialize( )) . "</pre>";
$r=$c->send($f);
$v=$r->value( );
if (!$r->faultCode( )) {
print "Email is". $email . " is " .
$v->scalarval( ) . "<br />";
print "<hr />I got this value back<br /><pre>" .
htmlentities($r->serialize( )). "</pre><hr />\n";
} else {
print "Fault: ";
print "Code: " . $r->faultCode( ) .
" Reason '" .$r->faultString( )."'<br />";
}
?>
I need to consume the WebService located at http://ws.myserver.com/register/index.php.
I pass the email as a parameter and then the XMLRPC.inc library will encode it using base64.
I've got a good XML request shown below:
<?xml version="1.0"?>
<methodCall>
<methodName>existsEmail</methodName>
<params>
<param>
<value><base64>dnJvZHJpZ3VlekBpY2NrLm5ldC5jbw==</base64></value>
</param>
</params>
</methodCall>
BUUUT, when I tried to get a response from the server I've to the following error
Fault: Code: -32601 Reason 'server error. requested method not found'
Any ideas? I'm getting crazy about how to call the existsEmail method from my PHP code...I'm sure it is there but I don't know if I'm missing something..
You are getting an error message (Specification for Fault Code Interoperability, version 20010516) from the XMLRPC endpoint you're communicating with.
It is a defined error code:
-32601 ---> server error. requested method not found
The RPC method you requested was not found by the server. Contact the support of the service you consume to get a list of all available methods. If that method should be available, contact the support and discuss the issue with them.
You asked in comment:
Is there any way [to] verify which methods are available?
That depends on the service. XMLRPC on sourceforge has a suggestion of defined methods you can call to list information about the functions available:
XML-RPC Introspection
system.listMethods
system.methodSignature
system.methodHelp
You can try if it works with your service, too. AFAIK those are common, I wrapped up a quick example, you find the full code below. See the output below the code as well.
$path = 'http://xmlrpc-c.sourceforge.net/api/sample.php';
printf("\n XMLRPC Service Discovery\n\n for: '%s'\n\n", $path);
$discovery = new Discovery($path);
$methods = $discovery->getMethods();
printf(" Method Summary:\n ===============\n", count($methods));
foreach ($methods as $i => $method)
{
printf(" %'.-2d %s\n", $i + 1, $method->getName());
}
printf("\n Method Details (%d):\n ===================\n", count($methods));
foreach ($methods as $i => $method)
{
printf(" %'.-2d %s\n", $i + 1, $method->getName());
printf("\n %s\n", $method);
printf("\n%s\n\n", preg_replace('/^/um', ' ', wordwrap($method->getHelp(), 46)));
}
Output:
XMLRPC Service Discovery
for: 'http://xmlrpc-c.sourceforge.net/api/sample.php'
Method Summary:
===============
1. debug.authInfo
2. sample.add
3. sample.sumAndDifference
4. system.listMethods
5. system.methodHelp
6. system.methodSignature
Method Details (6):
===================
1. debug.authInfo
<struct> debug.authInfo
Report any HTTP authentication in use
2. sample.add
<int> sample.add (<int>, <int>)
Add two numbers
3. sample.sumAndDifference
<struct> sample.sumAndDifference (<int>, <int>)
Add and subtract two numbers
4. system.listMethods
<array> system.listMethods (<string>)
This method lists all the methods that the
XML-RPC server knows how to dispatch
5. system.methodHelp
<string> system.methodHelp (<string>)
Returns help text if defined for the method
passed, otherwise returns an empty string
6. system.methodSignature
<array> system.methodSignature (<string>)
Returns an array of known signatures (an array
of arrays) for the method name passed. If no
signatures are known, returns a none-array
(test for type != array to detect missing
signature)
You can find the sourcecode here: XMLRPC Discovery Service
The parameters that I am talking about are __FILE__ and __LINE__ - those of the caller of the function, so that the function can use them in error reporting.
Let's say that I have two files and line 100 of file_1.php calls my_func() in file_2.php
I'd like to make that call my_func(__FILE__, __LINE__) so that if my_func encounters an error it can report it against file_1.php at line 100.
I do that since there are hundreds of calls to my_func and reporting the error to be in my_func() itself might not be informative (unless I dump the stack). And I don't want to have to manually type those two parameters a few hundred times.
In C I would do something like #define MY_FUNC my_func(__FILE, __LINE) - can I do something similar in PHP?
Unfortunately, PHP does not have any kind of macros. You could implement these yourself by running a command line tool like sed over some input to insert macros, but that is error prone and a bit sloppy.
To do what you want to do, you might consider the debug_backtrace function.
You can replicate C-like macros with the help of source file re-writing.
Write file macro.php:
<?php
$name = $_SERVER['PHP_SELF'];
$name = preg_replace('#\/#mui', '', $name);
$file = file_get_contents($name);
// get defined macros
preg_match_all('#\#macro\h+(\w+)\h+(.*)$#mui', $file, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
// delete macro definition
$file = str_replace($m[0], '', $file);
// substitute macro => value
$file = str_replace($m[1], $m[2], $file);
}
// save processed file
$new_name = '/var/tmp/' . $name . '.pr';
file_put_contents($new_name, $file);
include_once $new_name;
exit;
Now with such tool, usage is simple:
<?php
include_once "macro.php";
#macro DEBUG_INFO ;echo('<b> DEBUG_INFO: __FILE__ : ' . __FILE__ . ';__LINE__ : ' . __LINE__ . '</b>')
echo '<br>'.(1/2); DEBUG_INFO;
echo '<br>'.(1/0); DEBUG_INFO;
echo '<br>'.(0/0); DEBUG_INFO;
When executed outputs:
0.5 DEBUG_INFO: FILE : /var/tmp/test.php.pr;LINE : 7
INF DEBUG_INFO: FILE : /var/tmp/test.php.pr;LINE : 8
NAN DEBUG_INFO: FILE : /var/tmp/test.php.pr;LINE : 9
I have strong C background and always missed C-like macros in PHP. But hopefully we can inject some sort of replacement for it.
Nope. Use a stack trace: debug_backtrace(). You can retrieve the file and line of the caller, by simply looking at the second row in the returned array.
Unfortunately there is no C like Macros in PHP.
reading a debug_backtrace is tricky and I don't like that.
What I would like to throw an exception at error points then exception object it self contains the stack trace as well as the line number and file it's coming from.
catch (Exception $e)
{
$errorMessage = $e->getMessage() . " LINE: " .$e->getLine(). " FILE: " . $e->getFile();
}