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

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;
}

Related

JavaScript String replace second occurrence in XML

Hi have the following xml:
<?xml version="1.0" encoding="UTF-8"?>
<library>
<item>
<books>
<?xml version="1.0" encoding="UTF-8"?>
<Fiction>
<tt:Author>A</tt:Author>
<tt:BookName>45</tt:BookName>
</Fiction>
</books>
</item>
</library>
I want to basically replace the second occurence of the entire xml tag with blank space. So basically replace <?xml version="1.0" encoding="UTF-8"?> string which appears after the <books> opening tag with a space.
Any suggestions? I tried other links but could not get a working solution. The problem is there are ", ? and > in between the xml tag and the string replace function is considering that as an escape sequence character.
This is what I tried:
var stringToReplace = '<?xml version="1.0" encoding="UTF-8"?>';
var string = data.string;
//console.log(string);
var t=0;
var text = string.replace(/stringToReplace/g, function (match) {
t++;
return (t === 2) ? "Not found" : match;
});
console.log(text);
The above still prints both the xml tags
Assuming your XML always looks like this, you can use regular String methods to find the last occurrence of the string and remove it by creating substrings of the XML around it:
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<library>
<item>
<books>
<?xml version="1.0" encoding="UTF-8"?>
<Fiction>
<tt:Author>A</tt:Author>
<tt:BookName>45</tt:BookName>
</Fiction>
</books>
</item>
</library>`;
const strToReplace = '<?xml version="1.0" encoding="UTF-8"?>';
const index = xml.lastIndexOf(strToReplace);
// The new left- and right-sides of the string will omit the strToReplace
const newXml = xml.substring(0, index) + xml.substring(index + strToReplace.length);
console.log(newXml);

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

Xpages: Page containing multiple of the same custom controls are not unique

I have created a nice custom control for an input text box for US currency. I want to be able to put this CC on a page multiple times, so I have made the field name a property. Everything seems to work right if there is one control on a page, but if there are more than that then the code in the CC is not working as intended. I am trying to do some validation and editing in CSJS inside the CC, and trying to get the unique computed ID when I do so. But it is not working - the first value overwrites the second value, and other weird things happen.
My code is below:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom"
xmlns:xe="http://www.ibm.com/xsp/coreex"
createForm="false">
<style> .errorRed{ border: 2px solid red; }</style>
<xp:inputText
id="curText1"
value="#{viewScope.a}"
styleClass="pull-right"
style="width:200px;text-align:right"
defaultValue="0.00">
<xp:this.converter>
<xp:convertNumber
type="currency"></xp:convertNumber>
</xp:this.converter>
<xe:this.dojoAttributes>
<xp:dojoAttribute
name="input"
value="text-align: right">
</xp:dojoAttribute>
</xe:this.dojoAttributes>
<xp:eventHandler
event="onchange"
submit="false">
<xp:this.script><![CDATA[//Set some things
var thisID = '#{javascript:getClientId("curText1")}';
var thisCmp = XSP.getElementById(thisID);
var thisVal = XSP.getElementById(thisID).value;
//Error if this is not a number
if (isNaN(thisVal))
{thisCmp.className = thisCmp.className + " errorRed";
return}
else
{thisCmp.className = thisCmp.className.replace(" errorRed","")}
//Must remove $ and any commas
y = thisVal.replace(',','');
z = y.replace('$','');
//Must fix to 2 decimal places
if ((typeof z) === 'string'){
z = parseFloat(z).toFixed(2)}
else {
z = z.toFixed(2)
}
//Now put it back in the field
thisID.value = parseFloat(z);
XSP.partialRefreshPost(thisID);]]></xp:this.script>
</xp:eventHandler>
</xp:inputText>
</xp:view>
I am adding my modified code:
Custom Control:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom"
xmlns:xe="http://www.ibm.com/xsp/coreex"
createForm="false">
<style>.errorRed{ border: 2px solid red; }</style>
<xp:scriptBlock
id="scriptBlock1"
type="text/javascript">
<xp:this.value><![CDATA[formatNumber = function(thisID) {
var thisCmp = XSP.getElementById(thisID);
var thisVal = XSP.getElementById(thisID).value;
//Must remove currency symbol and any commas
y = thisVal.replace(',','');
z = y.replace('$','');
//Error if this is not a number
if (isNaN(z))
{thisCmp.className = thisCmp.className + " errorRed";
return}
else
{thisCmp.className = thisCmp.className.replace(" errorRed","")}
//Must fix to 2 decimal places
if ((typeof z) === 'string')
{z = parseFloat(z).toFixed(2)}
else
{z = z.toFixed(2)}
//Now put it back in the field
thisID.value = parseFloat(z);
XSP.partialRefreshPost(thisID,{execId:thisID, immediate: true});
}]]></xp:this.value>
</xp:scriptBlock>
<xp:inputText
id="curText1"
styleClass="pull-right"
style="width:200px;text-align:right"
defaultValue="0.00"
value="#{compositeData.price}">
<xp:this.converter>
<xp:convertNumber
type="currency"
currencySymbol="$">
</xp:convertNumber>
</xp:this.converter>
<xp:this.dojoAttributes>
<xp:dojoAttribute
name="input"
value="text-align: right">
</xp:dojoAttribute>
</xp:this.dojoAttributes>
<xp:eventHandler
event="onblur"
submit="false">
<xp:this.script><![CDATA[var thisID = '#{javascript:getClientId("curText1")}';
formatNumber(thisID);]]></xp:this.script>
</xp:eventHandler>
</xp:inputText>
<xp:inputText>
<xp:this.value><![CDATA[#{javascript:{"${"+compositeData.bla+"}"}}]]></xp:this.value>
</xp:inputText>
</xp:view>
Here is the code for the Xpage, with 2 custom controls:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:panel>
<xp:this.data>
<xe:objectData
var="doc">
<xe:this.createObject><![CDATA[#{javascript:var doc = new com.scoular.model.Project();
var unid = sessionScope.get("key");
if (unid != null) {
doc.loadByUnid(unid);
} else {
doc.create();
}
sessionScope.put("key",null);
return doc;}]]></xe:this.createObject>
</xe:objectData>
</xp:this.data>
</xp:panel>
<xp:panel id="numbers">
<xc:cc_CommonInputCurrency2
field="total1"
bla="#{doc.prjAmtColumn11}">
</xc:cc_CommonInputCurrency2>
</xp:panel>
<xp:panel id="panel1">
<xc:cc_CommonInputCurrency2
field="total2"
bla="#{doc.prjAmtColumn12}">
</xc:cc_CommonInputCurrency2>
</xp:panel>
</xp:view>
Your value property is bound to viewscope.a. In the rendering phase that scope has one and one value only, so all your fields are bound back to the same.
The better way is to use a parameter in your custom control to provide the value. So you would have something like <cc:moneyControl bla="document1.price">
Then you use a field you give the CSS attribute hidden and bind it to #{"${"+compositeData.bla+"}"} and let your dojo update that field. Saves you a server trip and having an extra field outside the CC.
How it works: the $ gets evaluated once and first and forms any valid data source, not only documents.
Hope that helps
I see two issues, first the code:
<xe:this.dojoAttributes>
<xp:dojoAttribute
name="input"
value="text-align: right">
</xp:dojoAttribute>
</xe:this.dojoAttributes>
should be using <xp:this.dojoAttributes> :
<xp:this.dojoAttributes>
<xp:dojoAttribute
name="input"
value="text-align: right">
</xp:dojoAttribute>
</xp:this.dojoAttributes>
Second, your isNaN check should come after your strip out the dollar sign and comma, like this:
//Must remove $ and any commas
y = thisVal.replace(',','');
z = y.replace('$','');
//Error if this is not a number
if (isNaN(z))
{
thisCmp.className = thisCmp.className + " errorRed";
return
}
else
{
thisCmp.className = thisCmp.className.replace(" errorRed","");
}
//Must fix to 2 decimal places
if ((typeof z) === 'string'){
z = parseFloat(z).toFixed(2)}
else {
z = z.toFixed(2)
}
If you need to have the field bound to a scoped field, one sure way to have a dynamic "private" variable inside a custom control is to name it using the clientId of from one of its components.
Example:
Create a panel that wraps the content of the custom control. Set an id on the panel to wrapper.
To set the scoped variable:
viewScope.put( getClientId( 'wrapper' ), 'someValue' )
To get the scoped variable:
viewScope.get( getClientId( 'wrapper' ) )
If you need access to the scoped variable outside the custom control, you could specify the client id of a component in the XPage as field name (compositeData) for the custom control using the same logic.

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>

using xsl:stream of XSLT 2.1

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.

Categories