using xsl:stream of XSLT 2.1 - javascript

I have a javascript which converts which applies xsl to an xml.
I need to use XSLT 2.1 in order to use the feature xsl:stream.
Now the script is as follows :
main();
function main()
{
if ( WScript.Arguments.length != 3 )
{
WScript.Echo("Usage: runTransform.js <xslfilename> <xmlfilename> <outputfilename>");
WScript.Quit();
}
var xslfilename = WScript.Arguments.Item(0);
var xmlfilename = WScript.Arguments.Item(1);
var outputfilename = WScript.Arguments.Item(2);
var doc = LoadDOM(xmlfilename);
var xsl = LoadDOM(xslfilename);
var str = doc.transformNode(xsl);
var ado = new ActiveXObject("ADODB.Stream");
ado.Open();
ado.Position = 0;
ado.CharSet = "UTF-8";
ado.WriteText(str);
ado.SaveToFile(outputfilename, 2)
}
function LoadDOM(file)
{
var dom;
try {
dom = MakeDOM(null);
dom.load(file);
}
catch (e) {
alert("error" + e.description);
}
return dom;
}
function MakeDOM(progID)
{
if (progID == null) {
progID = "msxml2.DOMDocument.4.0";
}
var dom;
try {
WScript.Echo("ProgID is dom 4");
dom = new ActiveXObject(progID);
dom.async = false;
dom.validateOnParse = false;
//dom.resolveExternals = false;
}
catch (e) {
alert("MakeDom Error :" + e.description);
}
return dom;
}
function alert(str)
{
WScript.Echo(str);
}
The sample xml that I am trying is as follows :
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<transactions>
<transaction value="12.51"/>
<transaction value="3.99"/>
</transactions>
The xsl to be applied is as follows :
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="2.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:mode streamable="yes" />
<xsl:stream href="E:\test_folder_stream\transactions.xml">
<count>
<xsl:value-of select="count(transactions/transaction)" />
</count>
</xsl:stream>
</xsl:stylesheet>
The output which I get is as follows :
<?xml version="1.0"?>
Ideally I should get the output as :
<?xml version="1.0">
<count>2</count>
The script is executed as follows :
test.js transactions.xsl transactions.xml output.xml
The script does not throw any error .
Is the xsl that I have written incomplete ?
Any suggestions or links will be valuable .
Thanks in advance
Tazim.

I don't think there is any XSLT processor currently available which implements xsl:stream.
Saxon 9.3 implements many of the streaming features in the XSLT 2.1 (now XSLT 3.0) working draft, but not yet the xsl:stream instruction. I suspect you are using an XSLT 1.0 processor. If you specify version="2.1" in a stylesheet and throw it at an XSLT 1.0 processor, it will ignore any children of the xsl:stylesheet element that it doesn't understand.
In fact xsl:stream is defined in XSLT 3.0 as an instruction, so it can't appear as a child of xsl:stylesheet - it needs to go in a function or template.
If you need streamed processing, get yourself a copy of Saxon 9.3 Enterprise Edition, and read the documentation carefully to see what subset of the working draft is currently implemented. You won't be able to use it from JavaScript, unfortunately.

Related

How do I declare then use a variable within a CDATA block?

I have an XSL/XML/JS file. It was written by someone who is not working here any more, and I normally only deal with SQL, so Im at a loss as to how to achieve what I need to do
Im trying to add some variables into the file within the existing CDATA block. I then use the variables within a function. However, I have tried the below and variations of this, but keep getting a syntax error within the application (Dynamics AX). Am I doing something obviously wrong here, with either how I am declaring the variables or how I am using them? These are the only changes I have made, and without these changes there are no syntax or any other issues/errors.
<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:mxm="http://schemas.microsoft.com/dynamics/2008/01/documents/MxmServInterfaceOutboundAif"
xmlns:data="http://www.example.com/data" exclude-result-prefixes="xs xsi xsl">
<xsl:output method="text" encoding="UTF-8" indent="no" />
<msxsl:script language="JScript" implements-prefix="data">
<![CDATA[
//Minor Repairs email address
var MinorsEmail = xxx#domain.com
//Service Dept email address
var ServiceEmail = yyy#domain.com
//Major Repairs email address
var MajorsEmail = zzz#domain.com
//Select appropriate email to use
function EmailFrom(fault)
{
var type = fault.substr(0,2);
if (type == "MI")
{
var ret = MinorsEmail;
}
else
{
var ret = concat(ServiceEmail, "; ",MajorsEmail);
}
return ret;
}
Edit: Adding quotes around the variable values has solved part of the problem. The problem now is that the CONCAT does not function as intended. I get the following error now:
Variable concat has not been declared
Thanks to #Martin Honnen, the answer was to add quote to variable values, and to use + instead of CONCAT:
<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:mxm="http://schemas.microsoft.com/dynamics/2008/01/documents/MxmServInterfaceOutboundAif"
xmlns:data="http://www.example.com/data" exclude-result-prefixes="xs xsi xsl">
<xsl:output method="text" encoding="UTF-8" indent="no" />
<msxsl:script language="JScript" implements-prefix="data">
<![CDATA[
//Minor Repairs email address
var MinorsEmail = "xxx#domain.com"
//Service Dept email address
var ServiceEmail = "yyy#domain.com"
//Major Repairs email address
var MajorsEmail = "zzz#domain.com"
//Select appropriate email to use
function EmailFrom(fault)
{
var type = fault.substr(0,2);
if (type == "MI")
{
var ret = MinorsEmail;
}
else
{
var ret = ServiceEmail + "; " + MajorsEmail;
}
return ret;
}

How to perform XSLT transformation in Chrome using variables

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/.

How to find the node position of a value in an XML tree?

Based on a value I input on the page, I want to retrieve the relevant XML data.
For example, if I input/select option "Michigan" from the datalist input field on my page, I want to find the node position of Michigan in the XML document. By knowing the node position, I can retrieve other information from the XML document corresponding to Michigan such as GDP and POPULATION.
I know I should change [1] to a variable such as [i], but how should I code the function?
var n = document.getElementById("myInputId");
n.addEventListener("keyup", function(event) {
event.preventDefault();
if (event.keyCode === 13) {
document.getElementById("myButton").click();
}
});
function loadXMLDoc() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
myFunction(xmlhttp);
}
};
xmlhttp.open("GET", "state_data.xml", true);
xmlhttp.send();
}
function myFunction(xml) {
var x, i, xmlDoc;
xmlDoc = xml.responseXML;
x = xmlDoc.getElementsByTagName("UNIT")
var s = xmlDoc.getElementsByTagName("STATE")[1].childNodes[0].nodeValue;
document.getElementById("state").innerHTML = s;
var gElem = xmlDoc.getElementsByTagName("GDP");
var g = (gElem.length > 0) ? gElem[1].childNodes[0].nodeValue : "";
document.getElementById("gdp").innerHTML = g;
var pElem = xmlDoc.getElementsByTagName("POPULATION");
var p = (pElem.length > 0) ? pElem[1].childNodes[0].nodeValue : "";
document.getElementById("population").innerHTML = p;
var a = n.value
document.getElementById("inputValue").innerHTML = a;
xmlDoc.UNITs.forEach(function(e, z) {
var q = document.getElementById("inputValue").innerHTML;
if (e.properties.id == q) {
document.getElementById("nodePosition").innerHTML = z;
}
});
}
<body onload="loadXMLDoc()">
<input list="myInput" id="myInputId" value="">
<button id="myButton" onClick="loadXMLDoc()">submit</button>
<p>input value: <span id="inputValue"></span></p>
<p>XML tree node position of input value: <span id="nodePosition"></span></p>
<p>State: <span id="state"></span></p>
<p>GDP: <span id="gdp"></span></p>
<p>Population: <span id="population"></span></p>
<datalist id="myInput">
<option id="AL">Alabama</option>
<option id="CA">California</option>
<option id="MI">Michigan</option>
<option id="TX">Texas</option>
<option id="WI">Wisconsin</option>
</datalist>
Here's my XML:
<?xml version="1.0" encoding="UTF-8"?>
<STATE_DATA>
<UNIT>
<STATE>Wisconsin</STATE>
<GDP>232,300,000,000</GDP>
<POPULATION>5,800,000</POPULATION>
</UNIT>
<UNIT>
<STATE>Alabama</STATE>
<GDP>165,800,000,000</GDP>
<POPULATION>4,900,000</POPULATION>
</UNIT>
<UNIT>
<STATE>California</STATE>
<!-- Note: the GDP node for this unit is missing -->
<POPULATION>39,600,000</POPULATION>
</UNIT>
<UNIT>
<STATE>Texas</STATE>
<GDP>1,600,000,000,000</GDP>
<POPULATION>28,300,000</POPULATION>
</UNIT>
<UNIT>
<STATE>Michigan</STATE>
<GDP>382,000,000</GDP>
<POPULATION>10,000,000</POPULATION>
</UNIT>
</STATE_DATA>
Things are simplified somewhat if you resort to the xml handling functionality that comes with modern browsers.
The rewrite centers around XPath expressions. A complete intro is beyond the scope of this answer, but in a nutshell it's a pattern language to retrieve content from an xml tree.
The xpath expressions are used to extract the relevant elements from the xml file.
The solution does not require any prior modifications to the xml ( contrary to the prior revision of this solution ).
The code sample is standalone - just save it as a local html file or serve it from a http server. To make it work, the xml data is stored in a script element serving as a data island.
Changing that design back to fetching the xml data with an ajax call should be straightforward..
Consider the code a proof of concept presenting the structure of an xpath-based approach.
<!DOCTYPE html>
<!--
SO
datalist / xml handling
Q 51200490 (https://stackoverflow.com/questions/51200490/how-to-find-the-node-position-of-a-value-in-an-xml-tree/51201494)
A
-->
<html>
<head>
<title>SO sample</title>
<script>
// Setup of keypress event handler, default selection of xml data.
function setupEH () {
var n = document.getElementById("myInputId");
n.addEventListener("keyup", function(event) {
event.preventDefault();
if (event.keyCode === 13) {
document.getElementById("myButton").click();
}
});
loadXMLDoc('Alabama'); // comment out this line if you want a vanilla UI after loading the html page.
}
// Load the xml document
function loadXMLDoc( statelabel ) {
// The xml document is retrieved with the following steps:
// 1. Obtain the (in-document) source as a DOM node.
// 2. Extract textual content.
// 3. Instantiate the xml parser (a browser built-in)
// 4. Parse textual content into an xml document
//
// When retrieving the xml document by means of ajax, these steps will be handled by the library for you - a parsed xml document will be available as a property or through calling a method.
//
let x_xmlisland = document.getElementById("template_xml");
let s_xmlsource = x_xmlisland.textContent;
let parser = new DOMParser();
let xmlDoc = parser.parseFromString(s_xmlsource, "application/xml");
myFunction(xmlDoc, statelabel); // Actual work ...
}
// Processing the xml document
function myFunction(xmlDoc, statelabel) {
// debugger; // uncomment to trace
//
// Every bit of information is processed as follows:
// - Get the relevant xml subtree ( `UNIT` element of the selected state incl.descendants )
// - Extract the textual value.
// - Feed the textual value to the Html elements prsenting the result.
//
var xpr_current_unit = xmlDoc.evaluate("/STATE_DATA/UNIT[./STATE[./text() = '"+statelabel+"']]",xmlDoc,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);
var node_current_unit = xpr_current_unit.iterateNext();
//
// The subsequent calls to xmlDoc.evaluate set the current UNIT element as their context node ('starting point'/'temporary root' for the xpath expression).
// The context node is referenced by '.' (dot)
//
var xpr_s = xmlDoc.evaluate("./STATE/text()",node_current_unit,null,XPathResult.ORDERED_ANY_TYPE,null);
var node_s = xpr_s.iterateNext();
var s = node_s.textContent
document.getElementById("state").innerHTML = s;
var xpr_g = xmlDoc.evaluate("./GDP/text()",node_current_unit,null,XPathResult.ORDERED_ANY_TYPE,null);
var node_g = xpr_g.iterateNext();
var g = "Unknown";
if ( node_g !== null ) {
g = node_g.textContent;
}
document.getElementById("gdp").innerHTML = g;
var xpr_p = xmlDoc.evaluate("./POPULATION/text()",node_current_unit,null,XPathResult.ORDERED_ANY_TYPE,null);
var node_p = xpr_p.iterateNext();
var p = "Unknown";
if ( node_p !== null ) {
p = node_p.textContent;
}
document.getElementById("population").innerHTML = p;
// cf. https://stackoverflow.com/a/3437009
var xpr_u = xmlDoc.evaluate("count(./preceding::UNIT)+1.",node_current_unit,null,XPathResult.ORDERED_ANY_TYPE,null);
var n_ucount = xpr_u.numberValue;
document.getElementById("inputValue").innerHTML = s;
document.getElementById("nodePosition").innerHTML = n_ucount;
}
// Setup the submit click handler
function ehClick ( ) {
let node_choice = document.getElementById('myInputId');
loadXMLDoc(node_choice.value);
}
</script>
<style>
</style>
</head>
<body onload="setupEH()">
<script id="template_xml" type="text/xml"><?xml version="1.0" encoding="UTF-8"?>
<STATE_DATA>
<UNIT>
<STATE>Wisconsin</STATE>
<GDP>232,300,000,000</GDP>
<POPULATION>5,800,000</POPULATION>
</UNIT>
<UNIT>
<STATE>Alabama</STATE>
<GDP>165,800,000,000</GDP>
<POPULATION>4,900,000</POPULATION>
</UNIT>
<UNIT>
<STATE>California</STATE>
<!-- Note: the GDP node for this unit is missing -->
<POPULATION>39,600,000</POPULATION>
</UNIT>
<UNIT>
<STATE>Texas</STATE>
<GDP>1,600,000,000,000</GDP>
<POPULATION>28,300,000</POPULATION>
</UNIT>
<UNIT>
<STATE>Michigan</STATE>
<GDP>382,000,000</GDP>
<POPULATION>10,000,000</POPULATION>
</UNIT>
</STATE_DATA>
</script>
<input list="myInput" id="myInputId" value="">
<button id="myButton" onClick="ehClick()">submit</button>
<p>input value: <span id="inputValue"></span></p>
<p>XML tree node position of input value: <span id="nodePosition"></span></p>
<p>State: <span id="state"></span></p>
<p>GDP: <span id="gdp"></span></p>
<p>Population: <span id="population"></span></p>
<datalist id="myInput">
<option id="AL">Alabama</option>
<option id="CA">California</option>
<option id="MI">Michigan</option>
<option id="TX">Texas</option>
<option id="WI">Wisconsin</option>
</datalist>
</body>
</html>
References
XPath Programming (Document.evaluate) on MDN
Getting alternative values from html datalists
Determining xml element position with XPath

Create XML in JavaScript

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>

Problem in executing XSLT transform file in XUL JavaScript

I'm working on XUL and i'm trying to execute XSLT processor function in XUL using JavaScript.
I have JavaScript function where I'm can update new record to my XML file and save the XML file. After that I'm trying to execute the XSLT processor function but I couldn't load my XSL and XML file.
My working environment is in windows using Eclipse, XulBooster. Generally, to load any file I use ("File://C:/mercredi.xml") or ("C:/mercredi.xml"); both file path works fine in other functions even in the JavaScript function which I used the same file path to read and save the XML file.
1.I have copied the following code Listing6: from this website:
http://www.ibm.com/developerworks/xml/library/x-ffox3/index.html
function process()
{
//Create an XSLT processor instance
var processor = new XSLTProcessor();
//Create an empty XML document for the XSLT transform
var transform = document.implementation.createDocument("", "", null);
//Load the XSLT
transform.onload = loadTransform;
transform.load("file://C:/idgenerator.xsl");
//Triggered once the XSLT document is loaded
function loadTransform(){
//Attach the transform to the processor
processor.importStylesheet(transform);
source = document.implementation.createDocument("", "", null);
source.load("file://C:/mercredi.xml");
source.onload = runTransform;
}
//Triggered once the source document is loaded
function runTransform(){
//Run the transform, creating a fragment output subtree that
//can be inserted back into the main page document object (given
//in the second argument)
var frag = processor.transformToFragment(source, document);
}
}
Then I checked Mozilla website and followed the instructions, still I couldn't load my file.
2.The following code is copied from this website:
https://developer.mozilla.org/en/Using_the_Mozilla_JavaScript_interface_to_XSL_Transformations
Even in this function I couldn't load my XML file.
function xslt()
{
var processor = new XSLTProcessor();
var testTransform = document.implementation.createDocument("", "test", null);
// just an example to get a transform into a script as a DOM
// XMLDocument.load is asynchronous, so all processing happens in the
// onload handler
testTransform.addEventListener("load", onload, false);
testTransform.load("file://C:/mercredi.xml");
function onload() {
processor.importStylesheet(testTransform);
}
}
This is my JavaScript code to execute the process() function of XSLT processor.
function saveFile(output, savefile) {
//function from http://puna.net.nz/archives/Code/Mozilla%20XUL%20LOG%20-%20read%20local%20files%20and%20write%20local%20files.htm
//var savefile = "c:\\mozdata.txt";
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
} catch (e) {
alert("Permission to save file was denied.");
}
var file = Components.classes["#mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
file.initWithPath( savefile );
if ( file.exists() == false ) {
alert( "File Updated Successfully ");
file.create( Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 420 );
}
var outputStream = Components.classes["#mozilla.org/network/file-output-stream;1"]
.createInstance( Components.interfaces.nsIFileOutputStream );
/* Open flags
#define PR_RDONLY 0x01
#define PR_WRONLY 0x02
#define PR_RDWR 0x04
#define PR_CREATE_FILE 0x08
#define PR_APPEND 0x10
#define PR_TRUNCATE 0x20
#define PR_SYNC 0x40
#define PR_EXCL 0x80
*/
/*
** File modes ....
**
** CAVEAT: 'mode' is currently only applicable on UNIX platforms.
** The 'mode' argument may be ignored by PR_Open on other platforms.
**
** 00400 Read by owner.
** 00200 Write by owner.
** 00100 Execute (search if a directory) by owner.
** 00040 Read by group.
** 00020 Write by group.
** 00010 Execute by group.
** 00004 Read by others.
** 00002 Write by others
** 00001 Execute by others.
**
*/
outputStream.init( file, 0x04 | 0x08 | 0x20, 420, 0 );
var result = outputStream.write( output, output.length );
outputStream.close();
alert( "File Updated Successfully ");
clear();
process();
}
Why I want to execute to XSLT file in my XUL? is to generate a unique ID for my customer in the XML file.
Please help me What am I doing wrong here?!? Thank you very much.
This is my XSLT file:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="CONTACT">
<xsl:copy>
<Customer-Id>
<xsl:value-of select="generate-id(.)"/>
</Customer-Id>
<xsl:copy-of select="FirstName|LastName|gmail|yahoo| Hotmail |URL|Facebook-ID"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
For some reason this:
var testTransform = document.implementation.createDocument("", "test", null);
and
testTransform.addEventListener("load", onload, false);testTransform.load("file://C:/mercredi.xml");
it didn't work.
Then I realized that I'm using 'readFile function' in my JavaScript to load file. I used this function to load any file in XUL.
Here is the code:
function process()
{
var src = readFile("c:\\idgenerator.xsl");//load my XSl file
var parsed = (new DOMParser()).parseFromString(src, "text/xml");
var stylesheet = parsed.documentElement;
var processor = new XSLTProcessor();
processor.importStylesheet(stylesheet );
objXMLDoc = processor.transformToDocument(objXMLDoc);//load & transform my XML file
var serializer = new XMLSerializer();
var prettyString = serializer.serializeToString(objXMLDoc);
saveFile(prettyString, "C:\\mercredi.xml");//Save the XML file
}

Categories