Problem: I'm trying to return XML from a controller, instead of a HTML document. The controller only returns a document type of HTML and not XML.
Details: I'm trying to populate a series of 3 drop downs on a page dynamically from information in database tables. The first drop down is dependent on the selection from a radio button, the second values from the first drop down selection, and the third values from the second drop down selection (cascading drop downs). I'm using jquery ajax calls to actions connected to controllers (only) to return the value. Every is working fine except for one thing...the controller is returning HTML instead of XML.
The controller is extracting the information from the database and moving the results to the root, and then transforming it to xml with the following stylesheet.
The ensure_html_response is set to false in the xgate.xml file.
I'm using Webmaker 4 because we have not upgraded our Bizflow yet.
All the testing I've done is showing the document being returned as a HTML document type and not an XML one.
So what am I missing?
Details: I'm trying to populate a series of 3 drop downs on a page dynamically from information in database tables. The first drop down is dependent on the selection from a radio button, the second values from the first drop down selection, and the third values from the second drop down selection (cascading drop downs). I'm using jquery ajax calls to actions connected to controllers (only) to return the value. Every is working fine except for one thing...the controller is returning HTML instead of XML.
The controller is extracting the information from the database and moving the results to the root, and then transforming it to xml with the following stylesheet.
<?xml version="1.0" encoding="UTF-8"?>
<xsl :s tylesheet version="1.0" xmlns:mvc="http://www.hyfinity.com/mvc" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:template match="/">
<xsl:value-of select="." />
</xsl:template>
</xsl :s tylesheet>
The ensure_html_response is set to false in the xgate.xml file.
<xgate>
<product>mvc</product>
<plugins>
<sxforms delete_bound="true" mark_unbound="true" mark_bound="/mvc:eForm/mvc :D ata/WorkitemContext">true</sxforms>
<ensure_html_response>false</ensure_html_response>
<output_doctype doctype_public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype_system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">true</output_doctype>
<set_locale>false</set_locale>
</plugins>
</xgate>
I'm using Webmaker 4 because we have not upgraded our Bizflow yet.
All the testing I've done is showing the document being returned as a HTML document type and not an XML one.
So what am I missing?
RE: Return XML from Controller
Firstly, I don+?+?+?t think that your XSL transform is needed as you have already moved the data you want to return to the root of the document, and so don't need to use an XSL to restructure it.
Also, at the moment I think this XSL is likely to corrupt the data, as you are only returning the string values from within the XML from your transform due to using xsl:value-of rather than xsl:copy-of.
(For info, when you are placing the results from the XSL transform back into the factbase (which is the norm) then the output setting on the XSL is less important, as it will always place the results back into a combined XML DOM document.)
With this transform removed you should find that the platform is returning the content you require, but possibly with the wrong doctype and content type header.
If you need to stop the doctype declaration from being output then you can add a condition attribute to the output_doctype element in the xgate.xml configuration to make sure it only applies to html content, eg
<output_doctype doctype_public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype_system=http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd condition="/html">true</output_doctype>
Unfortunately though this wont impact the content type set in the response, which will still be 'text/html'. In some cases this might not be an issue, for example you could treat the response as a string and then parse it into an XML document using JavaScript. It will depend on the exact script you are using as to whether this is possible or not.
If you do need to change the content type header to the correct value, then your only option is to use a custom XGate plugin.
This would be a very simple plugin like the following though:
package com.mycompany; import com.hyfinity.utils.xml.XDocument; import com.hyfinity.utils.xml.DOMUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Test XGate plugin for outputting XML content instead of HTML. */ public class OutputXMLPlugin implements XGatePlugin { /** * Default constructor. */ public OutputXMLPlugin() { } /** * Process the request before it is passed to the platform. * @param input An XDocument object containing the current state of the XML message. * The document this contains should be updated as required. * @param request The HttpServletRequest object that defines the request being processed. * This provides access to any request pr seesion parameters etc. * @param response The HttpServletResponse object that will eventually be written to. * You should not write to this as that will be handled automatically, * but you may want to add a cookie, or set a header for example. */ public void processInput(XDocument input, HttpServletRequest request, HttpServletResponse response) { //ignore in this plugin } /** * Process the response recieved from the platform, before it is returned to the browser. * @param output An XDocument object containing the current state of the XML message (this will often be HTML). * The document this contains should be updated as required. * @param request The HttpServletRequest object that defines the request being processed. * This provides access to any request pr seesion parameters etc. * @param response The HttpServletResponse object that will eventually be written to. * You should not write to this as that will be handled automatically, * but you may want to add a cookie, or set a header for example. */ public void processOutput(XDocument output, HttpServletRequest request, HttpServletResponse response) { if (!output.getRootNode().getLocalName().equals("html")) { //assume not HTML content so output as XML response.setContentType("text/xml"); DOMUtils.getSerializer().serialize(output.getDocument(), response.getOutputStream()); response.getOutputStream().flush(); //stop the default response output.setDocument(null); } } }
I+?+?+?ve not tested this code, but it should hopefully get you started. You would need to compile this and make sure it is available in the runtime environment, and then update your xgate.xml file to reference it.
<xgate> <product>mvc</product> <plugins> <sxforms delete_bound="true" mark_unbound="true" mark_bound="/mvc:eForm/mvc :D ata/WorkitemContext">true</sxforms> <ensure_html_response>false</ensure_html_response> <output_doctype doctype_public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype_system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">true</output_doctype> <set_locale>false</set_locale> <custom_plugins> <!-- Include our custom plugin --> <custom_plugin name="XML Output Plugin" runtime_instance="com.mycompany.OutputXMLPlugin" priority="60"/> </custom_plugins> </plugins> </xgate>
I hope this helps.
Please let me know how you get on.
Regards,
Gerard
RE: Return XML from Controller
I figured the xsl was redundant, but thought it was necessary to force it into an xml doc type. But, I have actually found a way around it using jQuery. I changed the returned type in the function from "xml" to "text". Then parse the text use the parseXML function. That returns a valid xml document, which you save to an xml object. Here is the function I'm using to pull it off if anyone else want's to use this. The advantage of this is that you don't have to change <ensure_html_response> to false for it to work.
function loadBuildings() { $("#BUILDING").empty(); $.ajax({ type: "GET", url: "getXML.do?FORMACTION=buildings", dataType: "text", success: function(data){ var xmlDoc=$.parseXML(data); //use browser to change document to xml var $xml=$(xmlDoc); // convert to a jquery xml object $xml.find('record').each(function(){ //loop through the records var key = $(this).find('BLDG').text(); var val = $(this).find('BLDG_DESCR').text(); $("#BUILDING").append( "<option value='" + key + "'>" + val + "</option>" ); }); } }); }
Again, thanks for all the help. You guys are great! Always timely and helpful.
RE: Return XML from Controller
I have used this type of approach before and it has worked well.
And thanks for the kind words! :) We do try to provide helpful responses and greatly appreciate any feedback, both good and bad!
Regards,
Gerard