I am trying to access an XML file from a server in my javascript code.
I have an XML file like this:
-<stream version="1.2">
-<room id="simulator" time="128168557915">
-<dimention id=0 x="1.25" y="2.00">
<m mcu="160" sid="75">
</dimention>
</room>
-<room id="simulator" time="128168557928">
-<dimention id=0 x="1.95" y="1.86">
<m mcu="160" sid="55">
</dimention>
</room>
</stream>
this file is generated by an application and I can access it from a URL ( since I am using the simulator for this application the XML is accessible from http://localhost:8081/feed/demo)
This xml file is updated every few seconds and constantly growing.
I have a javascript code which I've added the following code to it in order to use the data from XML file:
<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("GET","http://localhost:8081/feed/demo",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;
document.write("<table border='1'>");
var x=xmlDoc.getElementsByTagName("room");
for (i=0;i<x.length;i++)
{
document.write("<tr><td>");
document.write(xmlDoc.getElementsByTagName("dimention")[i].getAttribute("x"));
document.write("</td><td>");
}
document.write("</table>");
</script>
Now here comes my problem: if I have the XML file saved on same drive as html page and I address it like this:
xmlhttp.open("GET","floor.xml",false);
it works fine, but when I pass the URL it doesn't. is there anything else I should do in case of loading the xml from URL?
my second question is that I want to use the text values returned by
xmlDoc.getElementsByTagName("dimention")[i].getAttribute("x")
in an if statement like this :
if (valuereturned = 2.00)
{
do sth
}
what is the best way to do that, since the returned value is a text.
I need the answer ASAP and I realy appriciate your help :-)
I know this is a tired and cliche answer for questions like this, but consider using jQuery.
It makes pulling data via AJAX much nicer, and things like your second question much easier.
What's the status code returned when you try to access via absolute URL?
Now here comes my problem: if I have the XML file saved on same drive as html page and I address it like this: xmlhttp.open("GET","floor.xml",false); it works fine, but when I pass the URL it doesn't. is there anything else I should do in case of loading the xml from URL?
Answer: You're being tripped by the same domain security feature of browsers. The Ajax call must be to the same domain that the page itself was loaded from.
my second question is that I want to use the text values returned by
xmlDoc.getElementsByTagName("dimention")[i].getAttribute("x")
in an if statement like this :
if (valuereturned = 2.00)
{do sth}
what is the best way to do that, since the returned value is a text.
Answer:
First off, you want the equality test (==) not assignment (=).
Second, type coercion may work (but you might have to reverse the operands):
if (2.00 == valuereturned)
{do sth}
But much better is to convert explicitly:
if (parseFloat(valuereturned) == 2.00)
{do sth}
If you really want to compare to 2 (rather than a float 2.0), then you'll be safer (more reliable) comparing integers:
if (parseInt(valuereturned) === 2)
{do sth}
If you stick with floats, you'll probably want to do some rounding since looking for exactly matching float values is usually not what you want.
Try this quick and dirty solution.
function includeJS(filename, callback, responcedata){
var page = document.getElementsByTagName('head')[0],
js = document.createElement('script'),
url = "http://query.yahooapis.com/v1/public/yql?q="+
"select%20*%20from%20xml%20where%20url%3D'"+encodeURIComponent(filename)+
"'%20and%20columns%3D'question%2Canswer'&format='+responcedata'+&callback=?";
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', url);
page.appendChild(js);
}
window.onload = includeJS;
Arguments:
filename - the url of your xml file.
responcedata - json or xml
callback - a function that accepts your responcedata, json returns an object, xml returns xml.
YQL For more information.
Related
I have a html file, where I keep some notes and other info, I frequently update it, so it got quite big. The problem with that was, that if I change something in the layout, it gets really cumbersome, because I have to change it in so many places. So I had the idea, to put all the data into a XML and transform it into HTML with XSLT.
This immediately brought me to the first issue: I'm not able to access the XML.
The first thing I tried was loading it through XMLHttpRequest:
function loadXMLDoc(filename)
{
if (window.ActiveXObject)
{
xhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
else
{
xhttp = new XMLHttpRequest();
}
xhttp.open("GET", filename, false);
xhttp.setRequestHeader('Content-Type', 'application/xml');
try {xhttp.responseType = "msxml-document"} catch(err) {} // Helping IE11
xhttp.send("");
return xhttp.responseXML;
}
But this gets blocked with "Reason: CORS request not HTTP". I know why I get it and I also know that there most likely is no way around that when using XMLHttpRequest. (except tampering with local browser security, which I don't want to do).
My next idea was to put the XML as string directly into the script and just parse it into a XML doc. Something like:
var rawXml = "
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar/>
<bar/>
</foo>
";
But this gets me a "Uncaught SyntaxError: "" string literal contains an unescaped line". So apparently javascript doesn't support any form of verbatim strings and I have to escape all the linebreaks with a \n. My problem with that is, that I'm going to loose the pretty formatting. So reading and editing the XML is going to be a pain. That's definitely something I want to avoid.
EDIT:
Thanks to #Taplar for pointing out, that I can use a template literal, which makes the latter approach work.
This solution is not optimal, since I use NotePad++ and I can either use syntax highlighting for HTML or XML, plus XML Tools syntax autocheck gets screwed over by all the HTML code. But so far it is the best solution I have. Should there be any other options left, I'd like to hear them!
(As other people already pointed out to use input type=file, this is no real viable solution for me. I want to open the HTML document and read it. But with the input elements I have to first pick the XML and the pick the XSL. That's kinda cumbersome over which I prefer the xml-as-string solution)
You should set the XMLHttpRequestInstance.responseType to 'document':
function loadXMLDoc(filename, func){
const x = new XMLHttpRequest;
x.open('GET', filename); x.responseType = 'document';
x.onload = d=>{
func(d);
}
x.send();
return x;
}
// here's how you would execute
loadXMLDoc('yourFile.xml', d=>{
const productNodeList = d.getElementsByTagName('product');
});
...and I mean the MOST basic way. I have a filename, and I want to get its contents in a string called contents in a javascript funcrion in an html page. Nothing dynamic, no input fields, no onload,.. the file is called contents.txt. All I want is a javascript function to just do that: get the file contents into the string.
Is there not something less than 5 lines long that does this? Firefox only. No checks, I don't care for any compatibility right now...
thanks!
Ps background: i am building a parser of some sort in JavaScript and for now I just want to test the darn thing with test data...
This is a simple approach, place the script tag at the end of the body. This will ensure the page is fully loaded before it executes.
<script>
function done()
{
var fileContents = this.response;
}
var xmlhttp;
xmlhttp=new XMLHttpRequest();
xmlhttp.addEventListener("load", done, false);
xmlhttp.open("GET","/contents.txt",true);
xmlhttp.send();
</script>
</body>
I've got an xml file. It is meant for being transformed by xslt processor. The specific template is ready, however it use some information from two additional xml files. All information is used to produce the proper output.
It works fine when I open the main xml file with my browser. The problem is: the result is just a fragment of website, it is an HTML element ready for being appended as a child. That is why I want to transform the xml with the xslt processor within a JavaScript function. Unfortunatelly, the result is half-way done. All what don't need the additional information from these two xml files imported by xpath expression is transformed well. The rest is shortly speaking absent.
JavaScript:
var xhttp = new XMLHttpRequest()
var xsltProcessor = new XSLTProcessor()
xhttp.open("GET", "contentTemplate.xsl", false)
xhttp.send()
xsltProcessor.importStylesheet(xhttp.responseXML)
function buildElement(what) {
var xmlDoc = document.implementation.createDocument("", "root", null)
xmlDoc.documentElement.appendChild(xmlDoc.createElement(what))
var resultDocumentFragment = xsltProcessor.transformToFragment(xmlDoc, document)
return resultDocumentFragment
}
xslt:
there is lots of stuff, I paste just the xslt with xpath expression
<xsl:variable name="extInfo" select="document('tagAvailableToAdd.xml')/root"/>
<xsl:for-each select="$extInfo/tag">
<option>
<xsl:attribute name="value"><xsl:value-of select="tagName"/></xsl:attribute>
<xsl:value-of select="description"/>
</option>
</xsl:for-each>
and that is just absent. Just like no information was delivered.
EDIT:
it works in firefox, doesn't in chrome. I need to improve it. Actually, I don't know how.
xslt:
there is lots of stuff, I paste just
the xslt with xpath expression
<xsl:variable name="extInfo" select="document('tagAvailableToAdd.xml')/root"/>
<xsl:for-each select="$extInfo/tag">
<option>
<xsl:attribute name="value"><xsl:value-of
select="tagName"/>
and that is just absent. Just like no
information was delivered.
Some possible reasons for this behaviour:
The URI of the XML file is not the right one. This is a relative URI and this specific URI will mace the XSLT processor look for a file named 'tagAvailableToAdd.xml' and residing at the base-uri of the stylesheet. However, in this case the stylesheet is obtained dynamically and this means it doesn't have any base-uri. This is the most possible reason for the problem.
The Javascript doesn't have permissions to access files in the local file system.
The document() function isn't allowed by default by the XSLT processor.
The text contained in the file is not a well-formed XML document.
The top element of the XML file is not named root.
Solution: Specify an absolute URI as the argument to the document() function.
I thought I had solved the problem, however an issue in firefox has occured.
Nevertheless, I concern chrome my native browser, that is why i'm glad I made it work in this program. That is the change I implemented in JavaScript:
function talkToServer(address, synch, func) {
func = typeof(func) != 'undefined' ? func : null
xhttp.open(method, address, synch)
xhttp.onreadystatechange = func
xhttp.send()
}
function getXPath(query) {
return document.evaluate(query, xhttp.responseXML, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null)
}
function buildElement(what) {
var xmlDoc = document.implementation.createDocument("", "root", null)
xmlDoc.documentElement.appendChild(xmlDoc.createElement(what))
switch(what) {
case "windowElement":
talkToServer("tagAvailableToAdd.xml", false)
var additionalInfo = getXPath("/root/tag")
var aim = xmlDoc.documentElement.getElementsByTagName("windowElement")[0]
for(i=0;i<additionalInfo.snapshotLength;i++)
aim.appendChild(additionalInfo.snapshotItem(i).cloneNode(true))
talkToServer("cssTemplates.xml", false)
additionalInfo = getXPath("/root/*")
aim.appendChild(xmlDoc.createElement("css"));
aim = aim.getElementsByTagName("css")[0]
for(i=0;i<additionalInfo.snapshotLength;i++)
aim.appendChild(additionalInfo.snapshotItem(i).cloneNode(true))
break;
}
var resultDocumentFragment = xsltProcessor.transformToFragment(xmlDoc, document)
return resultDocumentFragment
}
in xslt now I have all information in , so there is no need to import any external info.
main function is buildElement. I'm sure everybody can see what it does. It'a aim is to provide sth I can "paste" to HTML document.
In chrome it works. In firefox says: Node cannot be used in a document other than the one in which it was created" code: "4, and points at return statement in getXPath function. I don't know how ti fix it, but who cares, it is just firefox (I know it's stupid). In IE it suck, because xhttp is XHttpRequest object, but I believe, that when I provide ActiveX it should give what I want.
If you feel you can help me with the firefix issue, write a comment.
I have a c program which outputs a number of lines to another c program which stuffs them in a PHP page which is loaded with AJAX. The problem is that the output is a number of lines, which is fine to look at, but which, when viewed as HTML, lack line breaks.
The initial thought I had was obviously to put line breaks in with the output. -- That worked fine, especially since I was using responseText to handle the AJAX output. Now I have discovered that along with the raw text, a bit of metadata also needs to be part of the AJAX response. I jumped over to using responseXML, only to find that the tags no longer worked correctly. At this point I could slog through any number of tutorials to figure out how to work some more complicated mechanism, but I really just want a hack. Could I embed the metadata in an html comment and use the DOM to dig it out (I looked and don't see a good method to get to comments using the dom...)? Could I use the xml directly as html somehow? Could I use CDATA in the xml document(this doesn't seem hopeful)? Could I just use newlines until the code reaches the webpage and then have JS insert the br tags?
I don't need any other formatting, just line breaks, and all this needs to do is work, the less complex the better.
How about using a XSLT stylesheet to format your incoming XML. Save the following as an .html file for an example. Sources : http://www.w3schools.com/xsl/xsl_client.asp & http://www.w3schools.com/dom/dom_parser.asp
<html>
<head>
<script>
//YOUR XML FROM AJAX
var XML = "<top><meta><itemone>test meta</itemone></meta><rows><row>line one</row><row>line two</row><row>line three</row></rows></top>";
//A stylesheet to format the lines that come back.
var XSLT = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="/"><h2>Lines</h2><xsl:for-each select="descendant::row"><xsl:value-of select="self::*"/><br /></xsl:for-each></xsl:template></xsl:stylesheet>'
function loadXMLDoc(xml)
{
var tempXML;
//IE
if (window.ActiveXObject)
{
tempXML=new ActiveXObject("Microsoft.XMLDOM");
tempXML.loadXML(xml);
}
else if(window.DOMParser)
{
parser=new DOMParser();
tempXML=parser.parseFromString(xml,"text/xml");
}
return tempXML;
}
function displayResult()
{
var xmlDoc = loadXMLDoc(XML);
var xsltDoc = loadXMLDoc(XSLT);
// code for IE
if (window.ActiveXObject)
{
var ex=xmlDoc.transformNode(xsltDoc);
document.getElementById("example").innerHTML=ex;
}
// code for Mozilla, Firefox, Opera, etc.
else if (document.implementation && document.implementation.createDocument)
{
var xsltProcessor=new XSLTProcessor();
xsltProcessor.importStylesheet(xsltDoc);
var resultDocument = xsltProcessor.transformToFragment(xmlDoc,document);
document.getElementById("example").appendChild(resultDocument);
}
}
</script>
</head>
<body onload="displayResult()">
<div id="example" />
</body>
</html>
Thanks for all the good suggestions, but I eventually decided to just prepend a fixed number of descriptor bytes to each text response and then use the substring command to get either the descriptor bytes or the main text response.
This allows me to keep using the simpler response-text mechanism, and is otherwise uncomplicated.
I would have used custom headers but I realized that that would have required buffering the whole output in yet ANOTHER place since the php script actually only contains a single system() call, and has no idea what the C program behind it is doing.
i have a problem to access some file from different source.
for example i have html folder and xml folder in same directory.
then from html file i wanna access xml file in xml folder.
in html i have script to call file
xmlDoc=loadXMLDoc("../xml/note.xml");
why this path doesnt work as well?
this is my code of loadXmlDoc()
function loadXMLDoc(dname)
{
var xmlDoc;
if (window.XMLHttpRequest)
{
xmlDoc=new window.XMLHttpRequest();
xmlDoc.open("GET",dname,false);
xmlDoc.send("");
return xmlDoc.responseXML;
} // IE 5 and IE 6
else if (ActiveXObject("Microsoft.XMLDOM"))
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async=false;
xmlDoc.load(dname);
return xmlDoc;
}
alert("Error loading document");
return null;
}
I would suggest using root relative, loadXmlDoc('/xml/note.xml') as this will always start at the same point ( the root ) and you don't have to keep ascending up with ../../.
The path is relative to the current page location (the current page you're browsing).
I suggest using the full http:// url, such as loadXMLDoc("http://example.com/xml/note.xml") or loadXMLDoc("/xml/note.xml").
You'll need to better describe what you mean by "doesn't work". However, judging from your code I'm guessing you are trying to get an XMLDOM object back from an XML source. Whenever I have trouble with XML sources I find the following list helps me track down my problem
Have you checked these things?
Did you set your content type to text/xml?
Is your request actually making it to the server and back?
When you alert/examine the responseText, do you see anything that does not belong?
Is your XML properly formatted? Run it through a validator.
With more information about what is failing I'll be better able to help.
Best of luck!
Cheers.