I am trying to do an XSL transformation.
However, whenever the variable with a document fragment is referenced, the transformation seems to fail.
I created a JSFiddle to demonstrate the issue. The XML in the example is a dummy document to allow the XSLT to run.
What am I doing wrong?
Javascript:
var xml = [
'<p xmlns="http://www.w3.org/1999/xhtml">',
'<\/p>'
].join('\n');
var xsl = [
'<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">',
'<xsl:variable name="xmlVar">',
'<aaaa value="It works"\/>',
'<\/xsl:variable>',
'<xsl:template match="\/">',
'<ROOT>',
//works ok after commenting out
'<xsl:value-of select="$xmlVar\/aaaa\/#value"\/>',
'<\/ROOT>',
'<\/xsl:template>',
'<\/xsl:stylesheet>'
].join('\n');
var domParser = new DOMParser();
var xmlDoc = domParser.parseFromString(xml, 'application/xml');
var xslDoc = domParser.parseFromString(xsl, 'application/xml');
var xsltProc = new XSLTProcessor();
xsltProc.importStylesheet(xslDoc);
try{
var result = xsltProc.transformToFragment(xmlDoc, document);
} catch(exc) {
document.getElementById('error').innerHTML = exc;
}
function encodeStr(rawStr) { return rawStr.replace(/[\u00A0-\u9999<>\&]/gim,
function(i){
return '&#'+i.charCodeAt(0)+';'
});
}
document.getElementById('xslText').innerHTML = encodeStr(xsl);
document.getElementById('result').innerHTML = encodeStr((new XMLSerializer).serializeToString(result));
HTML:
<pre id='xslText'>
</pre>
<pre id='result'>
</pre>
<pre id='error'>
</pre>
In XSLT 1.0 you need to use an extension function like exsl:node-set (http://exslt.org/exsl/functions/node-set/index.html) to convert a variable value of type result tree fragment (https://www.w3.org/TR/xslt-10/#section-Result-Tree-Fragments) to a node-set to be able to use XPath on the nodes e.g.
var xml = [
'<p xmlns="http://www.w3.org/1999/xhtml">',
'<\/p>'
].join('\n');
var xsl = [
'<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:exsl="http://exslt.org/common" xmlns:msxml="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="exsl msxml">',
'<xsl:variable name="xmlVar">',
'<aaaa value="It works"/>',
'<\/xsl:variable>',
'<xsl:template match="/">',
'<div>',
'<xsl:choose><xsl:when test="function-available(\'exsl:node-set\')"><xsl:value-of select="exsl:node-set($xmlVar)/aaaa/#value"/><\/xsl:when><xsl:when test="function-available(\'msxml:node-set\')"><xsl:value-of select="msxml:node-set($xmlVar)/aaaa/#value"/><\/xsl:when><\/xsl:choose>',
'<\/div>',
'<\/xsl:template>',
'<\/xsl:stylesheet>'
].join('\n');
var domParser = new DOMParser();
var xmlDoc = domParser.parseFromString(xml, 'application/xml');
var xslDoc = domParser.parseFromString(xsl, 'application/xml');
var xsltProc = new XSLTProcessor();
xsltProc.importStylesheet(xslDoc);
try{
var result = xsltProc.transformToFragment(xmlDoc, document);
document.getElementById('result').appendChild(result);
} catch(exc) {
document.getElementById('error').innerHTML = exc;
}
<pre id='xslText'>
</pre>
<pre id='result'>
</pre>
<pre id='error'>
</pre>
Drawback in terms of cross-browser compatibility with client-side XSLT 1 is that Microsoft use MSXML 3 or 6 in IE and Edge to provide XSLT support and unfortunately MSXML has its own proprietary namespace for such an extension function instead of supporting EXSLT.
Fiddle updated to http://jsfiddle.net/29pwf84c/14/.
We are tyring to work on this xml in ie11 browser .
<script id="Customer" type="application/xml">
<form id="customer">
<firstname></firstname>
<middlename></middlename>
<lastname></lastname>
</form>
</script>
we are trying to set atttrbute for the node.
var parser = new DOMParser();
var fieldID = "firstname";
var formID = "Customer";
doc = parser.parseFromString(document.getElementById(formID).innerHTML, "application/xml");
x=doc.getElementsByTagName(fieldID);
for(i=0;i<x.length;i++)
{
doc.getElementsByTagName(fieldID)[i].setAttribute(attrName,value);
document.getElementById(formID).innerHTML = new XMLSerializer().serializeToString(doc);
}
We are able to set the attribute value ... but when serializing the node and saving it to innerHTML, the xml tags which are empty are getting changed to the following format.
Please help to convert this
<firstname />
<middlename attr="value"></middlename>
<lastname />
to
<firstname></firstname>
<middlename attr="value"></middlename>
<lastname></lastname>
I have a XML file that is used by Flash as string resource
I would like my JS to use that XML as well: is there an easy way to read and parse external XML file in JS ?
like resources.xml that contains:
<resources locale="en">
<sizeUp>Size up</sizeUp>
<sizeDown>Size Down</sizeDown>
<clearSearch>Clear search</clearSearch>
<wouldYouLikeToReport>Would you like to report this user for abuse ?</wouldYouLikeToReport>
<yes>Yes</yes>
....
If you want to get every node and the text it contains, try this:
var xml;
xml = '<resources locale="en">';
xml += '<sizeUp>Size up</sizeUp>';
xml += '<sizeDown>Size Down</sizeDown>';
$(xml).children().each(function(index, elem) {
var $element = $(elem);
var text = $element.text();
console.log('elem is ');
console.log(elem);
console.log('text is ');
console.log(text);
});
The output will be:
elem is
sizeup
text is
Size up
elem is
sizedown
text is
Size Down
If you are looking for the contents of a specific tag, you could do:
console.log('sizeUp is ');
console.log($(xml).find('sizeUp').text());
Is it possible to create an XML file with some data in JavaScript? I have the data stored in variables.
I've googled around a bit and it doesn't seem like it's talked about much. I thought I could use XMLWriter such as this:
var XML = new XMLWriter();
XML.BeginNode ("testing");
XML.Node("testingOne");
XML.Node("TestingTwo");
XML.Node("TestingThree");
XML.EndNode();
as stated in this tutorial: EHow Tutorial
However, when I execute this code, I get the following error:
ReferenceError: XMLWriter is not defined
How can I solve this error?
Disclaimer: The following answer assumes that you are using the JavaScript environment of a web browser.
JavaScript handles XML with 'XML DOM objects'.
You can obtain such an object in three ways:
1. Creating a new XML DOM object
var xmlDoc = document.implementation.createDocument(null, "books");
The first argument can contain the namespace URI of the document to be created, if the document belongs to one.
Source: https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocument
2. Fetching an XML file with XMLHttpRequest
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
var xmlDoc = xhttp.responseXML; //important to use responseXML here
}
xhttp.open("GET", "books.xml", true);
xhttp.send();
3. Parsing a string containing serialized XML
var xmlString = "<root></root>";
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xmlString, "text/xml"); //important to use "text/xml"
When you have obtained an XML DOM object, you can use methods to manipulate it like
var node = xmlDoc.createElement("heyHo");
var elements = xmlDoc.getElementsByTagName("root");
elements[0].appendChild(node);
For a full reference, see http://www.w3schools.com/xml/dom_intro.asp
Note:
It is important, that you don't use the methods provided by the document namespace, i. e.
var node = document.createElement("Item");
This will create HTML nodes instead of XML nodes and will result in a node with lower-case tag names. XML tag names are case-sensitive in contrast to HTML tag names.
You can serialize XML DOM objects like this:
var serializer = new XMLSerializer();
var xmlString = serializer.serializeToString(xmlDoc);
Consider that we need to create the following XML document:
<?xml version="1.0"?>
<people>
<person first-name="eric" middle-initial="H" last-name="jung">
<address street="321 south st" city="denver" state="co" country="usa"/>
<address street="123 main st" city="arlington" state="ma" country="usa"/>
</person>
<person first-name="jed" last-name="brown">
<address street="321 north st" city="atlanta" state="ga" country="usa"/>
<address street="123 west st" city="seattle" state="wa" country="usa"/>
<address street="321 south avenue" city="denver" state="co" country="usa"/>
</person>
</people>
we can write the following code to generate the above XML
var doc = document.implementation.createDocument("", "", null);
var peopleElem = doc.createElement("people");
var personElem1 = doc.createElement("person");
personElem1.setAttribute("first-name", "eric");
personElem1.setAttribute("middle-initial", "h");
personElem1.setAttribute("last-name", "jung");
var addressElem1 = doc.createElement("address");
addressElem1.setAttribute("street", "321 south st");
addressElem1.setAttribute("city", "denver");
addressElem1.setAttribute("state", "co");
addressElem1.setAttribute("country", "usa");
personElem1.appendChild(addressElem1);
var addressElem2 = doc.createElement("address");
addressElem2.setAttribute("street", "123 main st");
addressElem2.setAttribute("city", "arlington");
addressElem2.setAttribute("state", "ma");
addressElem2.setAttribute("country", "usa");
personElem1.appendChild(addressElem2);
var personElem2 = doc.createElement("person");
personElem2.setAttribute("first-name", "jed");
personElem2.setAttribute("last-name", "brown");
var addressElem3 = doc.createElement("address");
addressElem3.setAttribute("street", "321 north st");
addressElem3.setAttribute("city", "atlanta");
addressElem3.setAttribute("state", "ga");
addressElem3.setAttribute("country", "usa");
personElem2.appendChild(addressElem3);
var addressElem4 = doc.createElement("address");
addressElem4.setAttribute("street", "123 west st");
addressElem4.setAttribute("city", "seattle");
addressElem4.setAttribute("state", "wa");
addressElem4.setAttribute("country", "usa");
personElem2.appendChild(addressElem4);
var addressElem5 = doc.createElement("address");
addressElem5.setAttribute("street", "321 south avenue");
addressElem5.setAttribute("city", "denver");
addressElem5.setAttribute("state", "co");
addressElem5.setAttribute("country", "usa");
personElem2.appendChild(addressElem5);
peopleElem.appendChild(personElem1);
peopleElem.appendChild(personElem2);
doc.appendChild(peopleElem);
If any text need to be written between a tag we can use innerHTML property to achieve it.
Example
elem = doc.createElement("Gender")
elem.innerHTML = "Male"
parent_elem.appendChild(elem)
For more details please follow the below link. The above example has been explained there in more details.
https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/How_to_create_a_DOM_tree
xml-writer(npm package)
I think this is the good way to create and write xml file easy.
Also it can be used on server side with nodejs.
var XMLWriter = require('xml-writer');
xw = new XMLWriter;
xw.startDocument();
xw.startElement('root');
xw.writeAttribute('foo', 'value');
xw.text('Some content');
xw.endDocument();
console.log(xw.toString());
Simply use
var xmlString = '<?xml version="1.0" ?><root />';
var xml = jQuery.parseXML(xml);
It's jQuery.parseXML, so no need to worry about cross-browser tricks. Use jQuery as like HTML, it's using the native XML engine.
this work for me..
var xml = parser.parseFromString('<?xml version="1.0" encoding="utf-8"?><root></root>', "application/xml");
developer.mozilla.org/en-US/docs/Web/API/DOMParser
Only works in IE
$(function(){
var xml = '<?xml version="1.0"?><foo><bar>bar</bar></foo>';
var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.loadXML(xml);
alert(xmlDoc.xml);
});
Then push xmlDoc.xml to your java code.
Your code is referencing this library
You can include it, and then your code in question should run as is. If you want to do this without prepending the library & build it with builtin functions only - follow answer from #Seb3736.
In Browser Example
<html>
<head>
<script src="Global.js" language="javascript"></script>
<script src="XMLWriter.js" language="javascript"></script>
<script language="javascript" type="text/javascript">
function genXML(){
var XML = new XMLWriter();
XML.BeginNode ("testing");
XML.Node("testingOne");
XML.Node("TestingTwo");
XML.Node("TestingThree");
XML.EndNode();
//Do something... eg.
console.log(XML.ToString); //Yes ToString() not toString()
}
</script>
</head>
<body>
<input type="submit" value="genXML" onclick="genXML();">
</body>
</html>
i'd like to ask if anyone here is familiar wif xml who can give me some help...
http://www.plognow.com/xml/login.xml
and i hv a little function tht i use to break it up...
function dialogXML(varName,url){
if (window.XMLHttpRequest){
r[varName]=new XMLHttpRequest();
}else{
r[varName]=new ActiveXObject("Microsoft.XMLHTTP");
}
r[varName].onreadystatechange=function(){
if (r[varName].readyState==4 && r[varName].status==200){
var rep=r[varName].responseXML.getElementsByTagName('box')[0];
var title=rep.getElementsByTagName('title')[0].nodeValue;
var content=rep.getElementsByTagName('content')[0].nodeValue;
createDialog(title,content);
}
}
r[varName].open('GET',url,true);
r[varName].send();
}
well i'm not sure how XMLDOM works, but can i retrieve the inwards of one tag?(all the childs subchilds etc)like u'd do in innerHTML. thanks!
You can use jQuery to manipulate XML documents as well not just HTML documents. HTML documents are XML documents.
if (r[varName].readyState==4 && r[varName].status==200){
var xml = r[varName].responseXML;
var rep = $("box:first", xml);
var title = $("title:first", rep).text();
var content= $("content:first", rep).text();
createDialog(title, content);
}
If your question is how to retrieve xml tree structure then the answer is : using responseXML property of r[varName].