How can I traverse XML in an HTML document? - javascript

I need to save the data offline, so I save the data as XML. I don't know how to get the XML object with JavaScript.
<xml id=xmlData>
<data>
<tb1>
<id>1</id>
<name>1</name>
</tb1>
<tb1>
<id>2</id>
<name>2</name>
</tb1>
</data>
</xml>
<html id="MainForm">
<head id="Head1">
</head>
<body>
<script type="text/javascript">
var xmlDoc;
// code for IE
if (window.ActiveXObject)
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
}
// code for Mozilla, Firefox, Opera, etc.
else if (document.implementation.createDocument)
{
xmlDoc=document.implementation.createDocument("","",null);
}
else
{
alert('Your browser cannot handle this script');
}
xmlDoc.async=false;
xmlDoc.load("");//how can i get the xml?
var x=xmlDoc.documentElement.childNodes;
for (var i=0;i<x.length;i++)
{
if (x[i].nodeType==1)
{
//Process only element (nodeType 1) nodes
document.write(x[i].nodeName + ": ");
document.write(x[i].childNodes[0].nodeValue);
document.write("<br />");
}
}
</script>
</body>
</html>

Try this:
var txt='<xml id=xmlData><data><tb1><id>1</id> <name>1</name></tb1><tb1><id>2</id><name>2</name></tb1></data></xml>';
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);
}
var x=xmlDoc.documentElement.childNodes;
for (var i=0;i<x.length;i++)
{
if (x[i].nodeType==1)
{
//Process only element (nodeType 1) nodes
console.log(x[i].nodeName + ": ");
console.log(x[i].childNodes[0].nodeValue);
console.log("<br />");
}
}
Fiddle: http://jsfiddle.net/hB5E9/

I use a local variable in the document to do this. If you can get the XML as a string property of an object then this might be useful -
I have a somewhat similar usage in my application. I read an "XML" column from the SQL Azure DB through a service call and I get this XML data as a "string" property of the service return object.
Here is what I am doing to read that :
_LocalVariable= XMLFromString(DataObject.Filter);
$.each($(_LocalVariable).find("Filter"),
function (index,filterDataItem) {
$filterDataItem =$(filterDataItem);
var tFilterType =$filterDataItem.find("FilterType").attr("class");
var tOperator = $filterDataItem.find("Operator").attr("class");
var tValue = $filterDataItem.find("Value").text();
// Do more operations
});
//--------------------------------------------------------------------------------
//Parse XML from String
//--------------------------------------------------------------------------------
function XMLFromString(pXMLString) {
if (!pXMLString)
pXMLString = "<FilterRule></FilterRule>";
if (window.ActiveXObject) {
var oXML = new ActiveXObject("Microsoft.XMLDOM");
oXML.loadXML(pXMLString);
return oXML;
} else {
return (new DOMParser()).parseFromString(pXMLString, "text/xml");
}
}
Where my XML in the database is something like this -
<FilterRule>
<Filter id="1">
<FilterType id="AB11">Ranking</FilterType>
<Operator id="1">Equal To</Operator>
<Value>1</Value>
</Filter>
<Filter id="2">
<FilterType id="AB22">Segment</FilterType>
<Operator id="1">Equal To</Operator>
<Value>2</Value>
</Filter>
<Logic>Or</Logic>
</FilterRule>

Related

Error thrown with Microsoft.XMLDOM XML Parser in Edge with XML string content

I'm getting the following error with the Microsoft.XMLDOM XML parser in Microsoft EDGE:
Script(1,1)
Sometimes it says start tag does not match end tag. And other times it gives another error. I wish I could provide the actual error messages but I'm away from a Windows machine and this is what I remember from memory.
The exact same XML content works in Firefox and other browsers. Can anyone see what is going on? This could be an easy fix but again I don't have a Windows computer.
Here is my XML:
<s:RichText x="118" visible="true" y="238" text="Text" fontSize="58.73271028037384">
<s:filters>
<BorderStrokeFilter alpha="1" angle="45" blurX="3" blurY="3" color="#FFFFFF" distance="0" hideObject="false" inner="false" knockout="false" multiplier="6" quality="3" strength="30" weight="3" xmlns="library://ns.flexcapacitor.com/flex"/>
<BorderStrokeFilter alpha="1" angle="45" blurX="3" blurY="3" color="#000000" distance="0" hideObject="false" inner="false" knockout="false" multiplier="6" quality="3" strength="30" weight="3" xmlns="library://ns.flexcapacitor.com/flex"/>
</s:filters>
<s:textFlow>
<s:TextFlow whiteSpaceCollapse="preserve" version="3.0.0" xmlns:s="library://ns.adobe.com/flex/spark"><s:p><s:span s:fontWeight="bold">Here is some text</s:span></s:p></s:TextFlow>
</s:textFlow>
</s:RichText>
Here is my validation method:
function validateXML(txt) {
// code for IE
if (window.ActiveXObject) {
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = "false";
xmlDoc.loadXML(txt);
if (xmlDoc.parseError.errorCode != 0) {
txt = "Error Code: " + xmlDoc.parseError.errorCode + "\\n";
txt = txt + "Error Reason: " + xmlDoc.parseError.reason;
txt = txt + "Error Line: " + xmlDoc.parseError.line;
return txt;
}
else {
return "No errors found";
}
}
// Mozilla, Firefox, Opera, etc.
else if (document.implementation.createDocument) {
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(txt, "text/xml");
if (xmlDoc.getElementsByTagName("parsererror").length > 0) {
return xmlDoc.getElementsByTagName("parsererror")[0];
}
else {
return "No errors found";
}
}
else {
return "Your browser does not support XML validation";
}
}
var xml = '<s:RichText x="118"></s:RichText>';
var result = validateXML(xml);
Can someone with Windows 10 run this? I've created a codepen here.
There was an error in my other code that was causing the error I was encountering but I also found out that when there's an error in Edge or IE they will log an error in the console.
Also, starting around IE 10 or 11 DOMParser is supported. The solution is to switch the if statement conditions to check for Domparser
if (window.DOMParser || document.implementation.createDocument)
and then put a try catch block around the parse method.
Although, it doesn't look like IE gives a line or column error information. I haven't been able to extensively test it.
The updated codepen can be tested:
function validateXML(txt) {
// Mozilla, Firefox, Opera, newer IE and Edge, etc.
if (document.implementation.createDocument) {
console.log("Before creating domparser");
var parser = new DOMParser();
try {
var xmlDoc = parser.parseFromString(txt, "text/xml");
} catch(error) {
console.log(error);
};
console.log("After DomParser instance. Errors: "+ xmlDoc.getElementsByTagName("parsererror").length);
if (xmlDoc.getElementsByTagName("parsererror").length > 0) {
return xmlDoc.getElementsByTagName("parsererror")[0];
}
else {
return "No errors found";
}
}
// code for older IE
else if (window.ActiveXObject) {
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = "false";
xmlDoc.loadXML(txt);
if (xmlDoc.parseError.errorCode != 0) {
txt = "Error Code: " + xmlDoc.parseError.errorCode + "\\n";
txt = txt + "Error Reason: " + xmlDoc.parseError.reason;
txt = txt + "Error Line: " + xmlDoc.parseError.line;
console.log("I work in Windows IE");
return txt;
}
else {
return "No errors found";
}
}
else {
return "Your browser does not support XML validation";
}
}
var xml = '<s:RichText x="118" xmlns:s="f">test</f/></s:RichText>';
var result = validateXML(xml);
console.log(result);
if (typeof result == "string") {
document.body.innerHTML = "<pre>"+result+"</pre>";
}
else {
document.body.innerHTML = "<pre>"+result.outerHTML+"</pre>";
}

Javascript and XML

I am working on JavaScript using HTML5 and I am stuck with a certain aspect. I want to do the following:
Create a table using JavaScript (which is fairly easy)
Extract details from a XML file that is available online
Enter the values in the table
For example, the linkhttp://www.tfl.gov.uk/tfl/syndication/feeds/cycle-hire/livecyclehireupdates.xml contains the information for cycle availability at each station
1. I need to create a table with two columns. One for 'Station Name' and the other for 'No of cycles available'
2. I need to write code that only takes in the above link as input and extracts values of 'Name' and 'nbEmptyDocks'.
Ex : <name> ABC,Surrey </name> <nbEmptyDocks> 10 </nbEmptyDocks>, how will I extract the values ABC,Surrey and 10 and place them in respective columns?
<!DOCTYPE html>
<html>
<body>
<script language= "JavaScript">
document.write('<br> <br><table width="50%" border="1">'); document.write('<th> Dock Station');
document.write('<th> Number of Cycles');
document.write('<br> <br><table width="50%" border="1">');
var Connect = new XMLHttpRequest();
Connect.open("GET", "http://www.tfl.gov.uk/tfl/syndication/feeds/cycle-hire/livecyclehireupdates.xml", false);
Connect.setRequestHeader("Content-Type", "text/xml");
Connect.send(null);
var TheDocument = Connect.responseXML;
var station = TheDocument.childNodes[0];
for (var i = 0; i < 5; i++)
{
var stations = station.children[i];
var name = stations.getElementsByTagName("name");
var avail = Customer.getElementsByTagName("nbEmptyDocks");
document.write("<tr><td>");
document.write( name[0].textContent.toString());
document.write("</td><td>");
document.write(avail[0].textContent.toString());
document.write("</td>");
document.write("</tr>");
}
document.write (" </table>");
</script>
</body></html>
On further reading, I understood that the above code might not work for Chrome, and I need one that works with chrome.
<html>
<body>
<script>
var xmlDoc;
var xmlloaded = false;
function initLibrary()
{
importXML("http:///www.somedomain.com/somesubdir/somefile.xml");
}
function importXML(xmlfile)
{
try
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", xmlfile, false);
}
catch (Exception)
{
var ie = (typeof window.ActiveXObject != 'undefined');
if (ie)
{
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
while(xmlDoc.readyState != 4) {};
xmlDoc.load(xmlfile);
readXML();
xmlloaded = true;
}
else
{
xmlDoc = document.implementation.createDocument("", "", null);
xmlDoc.onload = readXML;
xmlDoc.load(xmlfile);
xmlloaded = true;
}
}
if (!xmlloaded)
{
xmlhttp.setRequestHeader('Content-Type', 'text/xml')
xmlhttp.send("");
xmlDoc = xmlhttp.responseXML;
readXML();
xmlloaded = true;
}
}
</script>
</body>
</html>
But this doesnt seem to work either
I would suggest using Google API for grabbing RSS and rending it on your page: you can get started here.
As you say they are not tags themselves, for which it would've been fairly trivial to access them via DOM methods.
Instead, you will need to grab the textContent of the <title> and/or <description> nodes in each <item>. Once you have done that, you will need to do a little string processing. However, the strings are quite predictable, so this is easy:
var text = "Max Temp: 8°C (46°F), Min Temp: 5°C (41°F), Wind Direction: SW, Wind Speed: 8mph, Visibility: good, Pressure: 1002mb, Humidity: 92%, Pollution: n/a, Sunrise: 08:13GMT, Sunset: 16:40GMT";
var pairs = text.split(", "),
info = {};
for (var i=0; i<pairs.length; i++) {
var pair = pairs[i].split(": ");
info[pair[0]] = pair[1];
}
console.log(info)
// {"Max Temp":"8°C (46°F)","Min Temp":"5°C (41°F)","Wind Direction":"SW","Wind Speed":"8mph","Visibility":"good","Pressure":"1002mb","Humidity":"92%","Pollution":"n/a","Sunrise":"08:13GMT","Sunset":"16:40GMT"}
console.log(info["Max Temp"], info["Min Temp"])
// "8°C (46°F)", "5°C (41°F)"

Load an xml file with javascript in XSLT

I am stuck at this. I have an XSLT file that uses an XML file to retrieve data from it.
IN this XSLT file is also a javascript. It's purpose is to create counters to the 'for each' statement in the XSLT.
Now I need to add a feature to the javascript that gets a specific entry from the XML file.
I will paste a part of the xml here so I can explain further.
<ROW>
<Date>03-12-2013</Date>
<School>SvR</School>
<Locale>B1.04</Locale>
<Class>1236VUGK16</Class>
<Time>09:00-16:00</Time>
</ROW>
I need to get the data from "Date". But I do not know how to load an xml file in javascript to achieve this. I've found some html codes that tell me to xmlDoc.load will do this, but it does not. It will give me a syntax error. Is this because it is in XSLT? How can I achieve what I want?
you need 4 things
data.xml -> XML file
Openxml.js -> contains funciton to open Javascript
filejs.js -> contains function to read/write and others things with data.
index.html -> show information
part 1, your xml file:
<?xml version="1.0" encoding="UTF-8"?>
<events>
<ROW>
<Date>03-12-2013</Date>
<School>SvR</School>
<Locale>B1.04</Locale>
<Class>1236VUGK16</Class>
<Time>09:00-16:00</Time>
</ROW>
</events>
part 2:
unction OpenFile(fichXML)
{
var xmlDoc=undefined;
try
{
if (document.all) //IE
{
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
}
else //firefox
{
xmlDoc = document.implementation.createDocument("","",null);
}
xmlDoc.async=false;
xmlDoc.load(fichXML);
}
catch(e)
{
try { //otros safari, chrome
var xmlhttp = new window.XMLHttpRequest();
xmlhttp.open("GET",fichXML,false);
xmlhttp.send(null);
xmlDoc = xmlhttp.responseXML.documentElement;
return xmlDoc;
}
catch (e)
{
return undefined;
}
}
return xmlDoc;
}
part 3:
function Event(date)
{
this.date = date;
}
//funciton to charge XMLElements
function ChargeXMLElements()
{
try
{
xmlDoc=OpenFile("data.xml");
eventosXML=xmlDoc.getElementsByTagName('ROW');
if (eventosXML.length>0)
{
eventos=new Array(); //clase con los datos cargados
}
for(var i=0; i< eventosXML.length; i++)
{
xmlEvento=eventosXML[i];
fecha=xmlEvento.getElementsByTagName("DATE")[0].firstChild.nodeValue;
evento = new Evento(fecha);
eventos.push(evento);
}
return eventos;
}
catch(e)
{
alert("Error on the load data");
}
}
//show information take on previously function, and show on a table (with only 1 column)
function showinformation()
{
var tr;
var td;
var tabla;
var l=0;
ev= CargarXMLEventos();
auxUnEven=ev.pop();
tabla=document.getElementById("datos");
while (auxUnEven!=undefined)
{
tr=tabla.insertRow(l);
//creamos las columnas de la tabla
td=tr.insertCell(0);
td.innerHTML=auxUnEven.date;
/*td=tr.insertCell(1);
td.innerHTML=auxUnEven.hora;
td=tr.insertCell(2);
td.innerHTML=auxUnEven.comentario; */ //if you need more columns
l++;
auxUnEven=ev.pop();
}
if (l==0)
{
tabla=document.getElementById("datos");
tr=tabla.insertRow(l);
td=tr.insertCell(0);
td.innerHTML=" dont have events ";
}
}
part 4:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>example XML</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="filejs.js"></script>
<script type="text/javascript" src="Openxml.js"></script>
</head>
<body>
<table id="datos">
<script type="text/javascript">
showinformation();
</script>
</table>
</body>
</html>
i think that is functional but i don't know. I see the information here: http://elcaminillo.wordpress.com/2012/01/15/leer-xml-en-javascript/ (spanish, sorry)

Javascript XMLHTTPRequest Not Posting XML File

I have a content generator which contians textboxes, textareas and file input controls. All controls are in HTML. Once the save button is clicked I create my XML Document with the text entered into the HTML controls. Finally, I would like the user to be prompted to download the XML File. I am hoping I can do this using a POST method with a XMLHTTPRequest in Javascript. Once the XML Document is sent with the XMLHTTPRequest here is what happens,
Chrome: HTTP Status Code: 304
IE10: Nothing happens
Again, I would like the browser to prompt the user to download the XML File. Here is my code.
function generateBaseNodes() {
var xmlString = '<?xml version="1.0"?>' +
'<sites>' +
'<site>' +
'<textareas>' +
'</textareas>' +
'<textboxes>' +
'</textboxes>' +
'<images>' +
'</images>' +
'</site>' +
'</sites>';
if (window.DOMParser) {
parser = new DOMParser();
xmlDocument = parser.parseFromString(xmlString, "text/xml");
}
else // Internet Explorer
{
xmlDocument = new ActiveXObject("Microsoft.XMLDOM");
xmlDocument.async = false;
xmlDocument.loadXML(xmlString);
}
return xmlDocument;
}
function saveXmlFile(xmlDocument) {
if (window.XMLHttpRequest) { // IE7+, Chrome. Firefox, Opera. Safari
xmlhttp = new XMLHttpRequest();
}
else { // IE5 & IE6
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open('POST', 'http://localhost:57326/ContentGenerator.html', true);
xmlhttp.setRequestHeader('Content-type','text/xml');
xmlhttp.send(xmlDocument);
}
$('document').ready(function () {
$('#templateTab a').click(function (e) {
e.preventDefault()
$(this).tab('show')
})
//Create TextArea XML elements and add them
$('#btnSave').click(function () {
var x;
var xmlDocument = generateBaseNodes();
$('.content').each(function () { // Textarea
if ($(this).attr('id') != undefined) {
if ($(this).is('textarea')) {
// create article node with control id.
articleNode = xmlDocument.createElement($(this).attr('id'));
// append node to xmldocument
x = xmlDocument.getElementsByTagName('textareas')[0];
x.appendChild(articleNode);
// append text
articleNode.appendChild(xmlDocument.createTextNode($(this).text()));
}
if ($(this).is('input[type=text]')) { // Textbox
textNode = xmlDocument.createElement($(this).attr('id'));
x = xmlDocument.getElementsByTagName('textboxes')[0];
x.appendChild(textNode);
textNode.appendChild(xmlDocument.createTextNode($(this).text()));
}
} else { // Show error if a control does not have an ID assigned to it.
alert('The' + $(this).prop('type') + 'has an undefined ID.');
}
});
$('.imageContent').each(function () {
if ($('.imageContent input[type=file]')) { // Image url
// Validate file is an image
switch ($(this).val().substring($(this).val().lastIndexOf('.') + 1).toLowerCase()) {
case 'gif': case 'jpg': case 'png':
imageNode = xmlDocument.createElement($(this).attr('id'));
x = xmlDocument.getElementsByTagName('images')[0];
x.appendChild(imageNode);
imageNode.appendChild(xmlDocument.createTextNode($(this).val()));
break;
default:
$(this).val('');
// error message here
alert("not an image");
break;
}
}
});
saveXmlFile(xmlDocument);
});
});
I SUPPOSE I SHOULD POST MY XML OUTPUT
<sites>
<site>
<textareas>
<article1>sfdsfd</article1>
<article2>dsfsdf</article2>
</textareas>
<textboxes>
<title>dsfdsf</title>
<contentHeader>sdfsdf</contentHeader>
<linkContent>sdf</linkContent>
<link>sdfsd</link>
<relatedContent>sdfsdf</relatedContent>
<contentLink>dsf</contentLink>
<relatedArticle>sdfa</relatedArticle>
<articleLink>sfdf</articleLink>
</textboxes>
<images>
<imageHeader>C:\Images\Header.png</imageHeader>
<articleImage>C:\Images\Main.png</articleImage>
<articleImage2>C:\Images\Deals.png</articleImage2>
</images>
</site>
</sites>
Is there any way to make the browser prompt to download the XML File?
Yep. Convert your data to Blob, then generate a URL from it, which you can then use in an <a>, give that <a> a download attribute and the browser now knows it's to be saved not opened, then finally simulate a click on it. For example;
function txtToBlob(txt) {
return new Blob([txt], {type: 'plain/text'});
}
function genDownloadLink(blob, filename) {
var a = document.createElement('a');
a.setAttribute('href', URL.createObjectURL(blob));
a.setAttribute('download', filename || '');
a.appendChild(document.createTextNode(filename || 'Download'));
return a;
}
function downloadIt(a) {
return a.dispatchEvent(new Event('click'));
}
// and use it
var myText = 'foobar',
myFileName = 'yay.txt';
downloadIt(
genDownloadLink(
txtToBlob(myText),
myFileName
)
);
Try using Filesaver.js to get the user to download a file in memory.
Look also into Data URI's like this:
text file

Chrome and Safari XSLT using JavaScript

I have the following code that applies a XSLT style
Test.Xml.xslTransform = function(xml, xsl) {
try {
// code for IE
if (window.ActiveXObject) {
ex = xml.transformNode(xsl);
return ex;
}
// code for Mozilla, Firefox, Opera, etc.
else if (document.implementation && document.implementation.createDocument) {
xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
resultDocument = xsltProcessor.transformToFragment(xml, document);
return resultDocument;
}
} catch (exception) {
if (typeof (exception) == "object") {
if (exception.message) {
alert(exception.message);
}
} else {
alert(exception);
}
}
The code is working in IE and firefox but not in Chrome and Safari. Any ideas why?
Update
ResultDocument = xsltProcessor.transformToFragment(xml, document);
The line above is returning null. No error is being thrown.
Update
The code is not working as the xslt file contains xsl:include. Need to find a way to get the include working I will paste progress here
Update
It has been recomended that I use the http://plugins.jquery.com/project/Transform/ plugin. I am trying to use the client side libary as the example of include works here (http://daersystems.com/jquery/transform/).
The code works in IE but still not in chrome.
Test.Xml.xslTransform = function(xml, xsl) {
try {
$("body").append("<div id='test' style='display:none;'></div>");
var a = $("#test").transform({ xmlobj: xml, xslobj: xsl });
return a.html();
}
catch (exception) {
if (typeof (exception) == "object") {
if (exception.message) {
alert(exception.message);
}
} else {
alert(exception);
}
}
}
xml and xsl are both objects being passed in.
Update
I tried changing the XSL file to being something very simple with no include and Chrome is still not applying the stylesheet and IE is. The XSL that is being brought in as an object is:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rs="urn:schemas-microsoft-com:rowset"
xmlns:z="#RowsetSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:spsoap="http://schemas.microsoft.com/sharepoint/soap/"
>
<xsl:output method="html"/>
<xsl:template match="/">
<h1>test</h1>
</xsl:template>
</xsl:stylesheet>
Update
The end result that I want is for the xsl to be applied to the xml file. The xsl file has in it includes. I want the trasnfer to happen on the client ideally.
Updated
Rupert could you update the question with the xml and how you're calling Test.Xml.xslTransform ?
I got the xml using ie8
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><SearchListItemsResponse xmlns="http://schemas.microsoft.com/sharepoint/soap/"><SearchListItemsResult><listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
<rs:data ItemCount="1">
<z:row ows_Title="Test" ows_FirstName="Test 4" ows_UniqueId="74;#{1A16CF3E-524D-4DEF-BE36-68A964CC24DF}" ows_FSObjType="74;#0" ows_MetaInfo="74;#" ows_ID="74" ows_owshiddenversion="10" ows_Created="2009-12-29 12:21:01" ows_FileRef="74;#Lists/My List Name/74_.000" ReadOnly="False" VerificationRequired="0"/>
</rs:data>
</listitems></SearchListItemsResult></SearchListItemsResponse></soap:Body></soap:Envelope>
The code is being called as follows:
xsl = Test.Xml.loadXMLDoc("/_layouts/xsl/xsl.xslt");
var doc = Test.Xml.xslTransform(xData.responseXML, xsl);
xData is the xml returned by a web service.
If your XSLT is using xsl:include you might receive weird unexplainable errors but always with the same end result: your transformation failing.
See this chromium bug report and please support it!
http://code.google.com/p/chromium/issues/detail?id=8441
The bug is actually in webkit though. For more info here's another link which goes into more detail why it doesn't work.
The only way around this is to pre-process the stylesheet so that it injects the included stylesheets. Which is what a crossbrowser XSLT library like Sarissa will do for you automatically.
If your looking for jQuery solution:
http://plugins.jquery.com/project/Transform/ is a cross browser XSL plug-in. I've succesfully used this to get xsl:include working in the past without much hassle. You don't have to rewrite your xsl's this plugin will pre-process them for you. Definitely worth looking at as it's more lightweight then Sarissa.
UPDATE:
<html>
<head>
<script language="javascript" src="jquery-1.3.2.min.js"></script>
<script language="javascript" src="jquery.transform.js"></script>
<script type="text/javascript">
function loadXML(file)
{
var xmlDoc = null;
try //Internet Explorer
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async=false;
xmlDoc.load(file);
}
catch(e)
{
try //Firefox, Mozilla, Opera, etc.
{
xmlDoc=document.implementation.createDocument("","",null);
xmlDoc.async=false;
xmlDoc.load(file);
}
catch(e)
{
try //Google Chrome
{
var xmlhttp = new window.XMLHttpRequest();
xmlhttp.open("GET",file,false);
xmlhttp.send(null);
xmlDoc = xmlhttp.responseXML.documentElement;
}
catch(e)
{
error=e.message;
}
}
}
return xmlDoc;
}
function xslTransform(xmlObject, xslObject)
{
try
{
$("body").append("<div id='test'></div>");
var a = $("#test").transform({ xmlobj: xmlObject, xslobj: xslObject });
}
catch (exception)
{
if (typeof (exception) == "object" && exception.message)
alert(exception.message);
else alert(exception);
}
}
var xmlObject = loadXML("input.xml");
var xslObject = loadXML("transform.xsl");
$(document).ready(function()
{
xslTransform(xmlObject, xslObject);
});
</script>
</head>
<body>
</body>
</html>
This test html page works both in Chrome/FireFox/IE.
input.xml is just a simple xml file containing <root />
transform.xsl is the stripped down xsl you posted.
EDIT
It does however seem the $.transform has problems importing stylesheets from included files:
Here's how to fix this:
Locate
var safariimportincludefix = function(xObj,rootConfig) {
in jquery.transform.js and replace the entire function with this:
var safariimportincludefix = function(xObj,rootConfig) {
var vals = $.merge($.makeArray(xObj.getElementsByTagName("import")),$.makeArray(xObj.getElementsByTagName("include")));
for(var x=0;x<vals.length;x++) {
var node = vals[x];
$.ajax({
passData : { node : node, xObj : xObj, rootConfig : rootConfig},
dataType : "xml",
async : false,
url : replaceref(node.getAttribute("href"),rootConfig),
success : function(xhr) {
try {
var _ = this.passData;
xhr = safariimportincludefix(xhr,_.rootConfig);
var imports = $.merge(childNodes(xhr.getElementsByTagName("stylesheet")[0],"param"),childNodes(xhr.getElementsByTagName("stylesheet")[0],"template"));
var excistingNodes = [];
try
{
var sheet = _.xObj;
var params = childNodes(sheet,"param");
var stylesheets = childNodes(sheet,"template");
existingNodes = $.merge(params,stylesheets);
}
catch(exception)
{
var x = exception;
}
var existingNames = [];
var existingMatches = [];
for(var a=0;a<existingNodes.length;a++) {
if(existingNodes[a].getAttribute("name")) {
existingNames[existingNodes[a].getAttribute("name")] = true;
} else {
existingMatches[existingNodes[a].getAttribute("match")] = true;
}
}
var pn = _.node.parentNode;
for(var y=0;y<imports.length;y++) {
if(!existingNames[imports[y].getAttribute("name")] && !existingMatches[imports[y].getAttribute("match")]) {
var clonednode = _.xObj.ownerDocument.importNode(imports[y],true);
//pn.insertBefore(clonednode,_.xObj);
pn.insertBefore(clonednode,childNodes(_.xObj,"template")[0]);
}
}
pn.removeChild(_.node);
} catch(ex) {
}
}
});
}
return xObj;
};
Now using the previously pasted test index.html use this for transform.xsl:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:include href="include.xsl" />
<xsl:output method="html"/>
<xsl:template match="/">
<xsl:call-template name="giveMeAnIncludedHeader" />
</xsl:template>
</xsl:stylesheet>
And this for include.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="giveMeAnIncludedHeader">
<h1>Test</h1>
</xsl:template>
</xsl:stylesheet>
With the previously posted fix in jquery.transform.js this will now insert the included <h1>Test</h1> on all the browsers.
You can see it in action here: http://www.mpdreamz.nl/xsltest
This is not an answer to the original question but during my search over internet looking for a sample xslt transformation that works on chrome I found links to this thread many times. I was looking for a solution that doesn't use any open-source or third party libraries/plugins and works well with silverlight.
The problem with chrome and safari is the limitation that prevents loading xml files directly. The suggested workaround at http://www.mindlence.com/WP/?p=308 is to load the xml file via any other method and pass it as a string to the xslt processor.
With this approach I was able to perform xsl transformations in javascript and pass on the result to silverlight app via HTML Bridge.

Categories

Resources