Can you get them to work with any other XML-RPC API? Usually the examples include a URL to a test server, where you can input two numbers using a method and get the sum of them back.
If you can get that working, I might be able to help you modify it to work with Wikidot instead.
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
Oh. Thanks Shane.
I have found several working examples but don't have the links.
I also found this: http://ajaxian.com/archives/tomic-xml-rpc-javascript-client
The main problem is with associative arrays. I don't know how to do them on JS.
Kenneth Tsang (@jxeeno)
Try getting one of those "working examples" to actually work for you. Then, change this:
- The URL to Wikidot's API URL
- The method to the parameter-less system.listMethods() method (should be easier to get that working than trying to use page.save() immediately)
- Find out how to give the XML-RPC client your authentication (username and password, where password is your API key)
If you do that, it should start working…
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
Any luck tsangk? I was hoping you might have an example of a working Javascript program for me to work from. Want to try a few things of my own but you know more about the language than I do.
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
I thought I hit a dead end. I was just wondering if there is a problem with cross-domain security. I was looking up several sites to see if it was an issue but I just don't have the time at the moment to try things out. English and Maths is more important (:
Kenneth Tsang (@jxeeno)
Usually JavaScript doesn't allow you to connect to server from other domain, so you need to connect to XMLRPC on the same domain the JavaScript is run from. Usually this means the server needs to have a small proxy that allows you to connect to other servers via itself.
Piotr Gabryjeluk
visit my blog
So in other words, I can't do anything about it unless WikidotI create a proxy?
Kenneth Tsang (@jxeeno)
@tsangk, what just came into my mind is that you can use XMLRPC in the [[html]] blocks!
HTML blocks are served from http://your-site.wdfiles.com/… and you can alter the domain in the XMLRPC endpoint to match this domain (so it's https://your-site.wdfiles.com/xml-rpc-api.php). You will only need to force authorization of users by redirecting them to https://your-site.wdfiles.com/xml-rpc-api.php — browser will ask them for user/password and when they complete it, you should be able to use a JavaScript XMLRPC library to do any nasty stuff for them.
It may be required to run the whole [[html]] block using https.
Piotr Gabryjeluk
visit my blog
Surprise! Got system.listMethods working. Can't get associative working!
Here it is anyways: https://kenneth.wikidot.com/xmlrpc/noredirect/true
Kenneth Tsang (@jxeeno)
Try:
{'site': 'tsangk', 'other-param': 'value'}
It's JavaScript notation of Object that should be converted to XMLRPC struct, because it's the closest possible representation of it.
Piotr Gabryjeluk
visit my blog
var request = new XmlRpcRequest("https://"+document.getElementById("username").value+":"+document.getElementById("key").value+"@my-sandbox.wdfiles.com/xml-rpc-api.php", 'pages.get_one');
request.addParam({'site': 'tsangk', 'page': 'start'});
var response = request.send();
alert(response.fullname);
IMO this should work and alert "start".
Piotr Gabryjeluk
visit my blog
Here: http://www.xmlrpc.com/spec
Request Example
POST /RPC2 HTTP/1.0 User-Agent: Frontier/5.1.2 (WinNT) Host: betty.userland.com Content-Type: text/xml Content-length: 181 <?xml version="1.0"?> <methodCall> <methodName>examples.getStateName</methodName> <params> <param> <value><i4>41</i4></value> </param> </params> </methodCall>
Response Example
HTTP/1.1 200 OK Connection: close Content-Length: 158 Content-Type: text/xml Date: Fri, 17 Jul 1998 19:55:08 GMT Server: UserLand Frontier/5.1.2-WinNT <?xml version="1.0"?> <methodResponse> <params> <param> <value><string>South Dakota</string></value> </param> </params> </methodResponse>
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
is this correct?
<methodCall><methodName>categories.select</methodName><params><struct><member><name>site</name><value><string>kenneth</string></value></member></struct></params></methodCall>
Kenneth Tsang (@jxeeno)
Yes, it's struct for the Wikidot API.
Every method in the Wikidot API accepts one parameter. And that one parameter is a struct, containing parameters…
I'm not sure why it's done this way, but I'm sure there's a good reason for it. Gabrys may be able to explain.
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
My guess is that you want this (what I've added is in blue):
<?xml version="1.0"?>
<methodCall>
<methodName>categories.select</methodName>
<params>
<param>
<struct><member><name>site</name><value><string>kenneth</string></value></member></struct>
</param>
</params>
</methodCall>
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
Every method in the Wikidot API accepts one parameter. And that one parameter is a struct, containing parameters…
I'm not sure why it's done this way, but I'm sure there's a good reason for it. Gabrys may be able to explain.
Structs are the most flexible types for XMLRPC communication, they don't force you to use any specific types inside and are very easy to use in many programing languages. Also having one parameter makes it extremely easy to parse on the server side.
Some programming languages have limited support for XMLRPC so we decided to make the work for them easier, this is why we only use basic types: strings, ints, arrays and structs. That's why we don't return dates as dates (but as strings in well-implemented and human-readable format, that you can easily and fast convert) and binary data as base64 type (but as base64-encoded strings, that you can easily and fast convert to binary data).
Piotr Gabryjeluk
visit my blog
Got it!!
<methodCall> <methodName>page.save</methodName> <params> <param> <value> <struct> <member> <name>site</name> <value> <string>test</string> </value> </member> </struct> </value> </param> </params> </methodCall>
Kenneth Tsang (@jxeeno)
Well, all of the examples I saw for using XML-RPC with Java assumed that people were using regular parameters, which is why it took me several weeks to finally get it working ;-) (no exaggeration)
Now that I understand what to do, I like it because it makes my code more readable. I'm adding parameters to a HashMap, which basically looks like this:
(pseudocode)
Define map
map.put ( "site" = "leiger" );
map.put ( "page" = "start" );
sendToApi(map);
Instead of:
(pseudocode)
sendToApi( "leiger", "start" );
The first one makes someone reading the code easily tell what each variable means… the second one you've got to look at the method signature to figure it out e.g. "Does the first one represent a site name or user's name?"
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
tsangk: Got it!!
Cool :) So… how do we pass that to the API using Javascript?
Will wait and see what edits you make to your test page…
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
No edits there yet! Here is the code:
<script type="text/javascript"> if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("POST","https://username:key@my-sandbox.wdfiles.com/xml-rpc-api.php",false); xmlhttp.send("<methodCall><methodName>categories.select</methodName><params><param><value> <struct><member> <name>site</name> <value> <string>kenneth</string> </value></member></struct></value> </param> </params></methodCall>"); xmlDoc=xmlhttp.responseXML; if(xmlhttp.status == 200) alert(xmlhttp.responseText); </script>
Kenneth Tsang (@jxeeno)
leiger: this was more or less, what I meant. Also if a method signature changes, you need to update code, if we add optional parameter to our struct, old code works.
I'm not sure if XMLRPC has optional parameters, but if it does it's also easier to build the struct (HashMap) than to have a huge if/else construction that passes those optional parameters depending on what your user want.
Piotr Gabryjeluk
visit my blog
Okay… so if I wanted to do that for the categories.select, but use the other code for system.listMethods, all I need to do is to put each into a Javascript method, then call a different method depending on what the user chooses in the select/combo box?
I'll try it now… thanks :D
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
Since Wikidot API is a subset of XMLRPC, I think I can make a wikidot-api JavaScript library easily using jQuery (that would handle XML encoding/decoding and what tsangk named xmlhttp).
Piotr Gabryjeluk
visit my blog
Learning is never wasted ;-)
The XML-RPC specification is surprisingly short and easy to read: http://www.xmlrpc.com/spec
And done! Accepts params (: Example below (:
<script type="text/javascript"> function apicall(method,param,user,key){ //var method="categories.select"; var payloadxml="<?xml version='1.0'?><methodCall>";//Start Call payloadxml+="<methodName>"+method+"</methodName>";//Call method payloadxml+="<params><param><value><struct>";//Argument pre-bracket for ( keyVar in param ) { payloadxml+="<member><name>"+keyVar+"</name><value><string>"+param[keyVar]+"</string></value></member>"; } //payloadxml+="<member><name>site</name><value><string>kenneth</string></value></member>";//[TESTING ONLY] Do this for each payloadxml+="</struct></value></param></params></methodCall>";//End all here (: if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("POST","https://"+user+":"+key+"@my-sandbox.wdfiles.com/xml-rpc-api.php",false); xmlhttp.send(payloadxml); xmlDoc=xmlhttp.responseXML; if(xmlhttp.status == 200) var txt=xmlhttp.responseText; if (window.DOMParser) { parser=new DOMParser(); xmlDoc=parser.parseFromString(txt,"text/xml"); } else // Internet Explorer { xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); xmlDoc.async="false"; xmlDoc.loadXML(txt); } return txt; } var params = new Object(); params['site'] = 'kenneth'; params['page'] = 'blog:_start'; document.write(apicall("files.select",params,"user","key")); </script>
Kenneth Tsang (@jxeeno)
Can I ask what the point of adding the API key was? It will ask me for username and key anyway (:
Yes, I was wondering the same thing. Every time I click on one of the buttons it pops up and asks for authentication, so the API key box doesn't seem to be used.
If it matters, I'm using Chrome 6.0.472.63 on Windows 7 Professional.
Based on the examples you've given, it looks really simple. But I have a question about getting the return value…
Return values are passed to callback function, you should pass as a parameter:
w.select.categories({'site': 'blog', function(data) {
alert(data);
}});
Okay, you've got an in-line function… but will it also work with just this? The in-line function makes the code harder to read IMO. I haven't tried testing if this works yet.
var data = w.select.categories({'site': 'blog'});
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
I reckon it's a coding error. In the function, the variable app_name is the username.
EDIT: It is hardcoded in the demo with the username of wikidot-api-demo which doesn't exist (:
Kenneth Tsang (@jxeeno)
I reckon it's a coding error. In the function, the variable app_name is the username.
Yes, that's what it should be.
All you need to connect to the API is the API key - the 'username' field can be anything (it doesn't have to be your username).
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
JavaScript can handle remote connections asynchronously, that's why you use callback functions. You can force using synchronous version (pass true as third parameter to $.wikidot) and then API function just returns what server returns (decoded to JavaScript object of course). But using synchronous communication in JavaScript is not preferred, since it can block the browser.
About the user/password dialog, each browser may behave differently, Firefox allows me to pass user and password in URL, just like my lib does.
Piotr Gabryjeluk
visit my blog
I'm trying to get yours working Gabrys… having some problems. I'm guessing it still has to be a 'https' connection?
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs
About the user/password dialog, each browser may behave differently, Firefox allows me to pass user and password in URL, just like my lib does.
I found a bug in my code. It should work now without prompting user for user/password (if you passed the key to the input box instead).
Piotr Gabryjeluk
visit my blog
tsangk… could you please parse the XML and display it on the page so I can copy and paste it? ;-)
I need access to the API from on campus, and as I don't have my Java development tools with me (e.g. Eclipse IDE) it's a bit difficult. Tried to use yours today but it's useless if I can't copy and paste the results :S Sorry…
Shane Smith
ethicalwd.com - Blog - Wikidot Editor - Docs