I understand I cannot save XML content to a local file, because of security restrictions. but is there a way I can show the XML content in another browser window, as
Window.Open(xmlString, . .. );
that would work the same as -
Window.Open(URL, . . .);
I cannot use server-side language.
I can use javaScript \ jQuery. (I already use them to create the XML)
I can have a template XML file, near my HTML. Is there a way to display the template file and change its content ? almost the same as window.open: is it possible open a new window with modify its DOM or How to write JavaScript to a separate window? but I need to change XML nodes, and not HTML.
EDIT 1: try using myXmlWindow.document.write(xmlString)
=> I tried the suggested code -
var xmlString = xml2Str(xmlDocument);
myXmlWindow = window.open();
myXmlWindow.document.write(xmlString);
myXmlWindow.focus();
but it does not display the whole XML content, just the intern node values. and the new window still display "Connecting..." as it did not finish loading the content (missing close tag ???)
maybe I need to tell it is XML content and not HTML ???
my xmlString :
<root><device1>Name</device1><device2/><device3><Temprature_1>23.5</Temprature_1><Temprature_2>23.4</Temprature_2><Temprature_3>23.4</Temprature_3><Temprature_4>23.3</Temprature_4><Temprature_5>23.2</Temprature_5></device3></root>
the displayed content:
Name23.523.423.423.323.2
EDIT 2: my code -
function xml2Str(xmlNode) {
try {
// Gecko- and Webkit-based browsers (Firefox, Chrome), Opera.
return (new XMLSerializer()).serializeToString(xmlNode);
}
catch (e) {
try {
// Internet Explorer.
return xmlNode.xml;
}
catch (e) {
//Other browsers without XML Serializer
// alert('Xmlserializer not supported');
return('Xmlserializer not supported');
}
}
return false;
}
function fShow_xml_in_win() {
var xmlDocument = $.parseXML("<root/>");
var dev1 = xmlDocument.createElement('device1');
var dev2 = xmlDocument.createElement('device2');
var dev3 = xmlDocument.createElement('device3');
dev1.appendChild(xmlDocument.createTextNode('Name'));
xmlDocument.documentElement.appendChild(dev1);
xmlDocument.documentElement.appendChild(dev2);
xmlDocument.documentElement.appendChild(dev3);
var i;
var xNode;
for (i = 0; i < 5; i++) {
xNode = xmlDocument.createElement('Temprature_' + (i+1));
xNode.appendChild(xmlDocument.createTextNode( "myVal " + ((i+1) * 10) ));
dev3.appendChild(xNode);
}
var xmlString = xml2Str(xmlDocument);
alert(xmlString);
xmlString = "<?xml version='1.0' ?>" + xmlString; // I do not know how to add this node using parseXML :(
alert(xmlString);
myXmlWindow = window.open();
myXmlWindow.document.write(xmlString);
myXmlWindow.document.close(); // !! EDIT 3
myXmlWindow.focus();
return false;
}
EDIT 3: solved the "connecting..." problem
I just needed to add myXmlWindow.document.close();
You can open a blank window and then write content to it as follows:
myWindow=window.open('','','width=200,height=100')
myWindow.document.write(xmlString);
myWindow.focus()
You may need to do some work to format your xmlString, but I think this approach will do what you want. If your xmlString is formatted, try adding:
<?xml version="1.0" ?>
to the start of your string.
My understanding from your post, are
1.(From your firts point)
you get xml from somewhere which is not your control. My suggestion is why don't you get as JSON?
2.(From your second point)
If those XML is created by you means, Why aren't you try to write those XML from reference?
For example:
var reference = window.open();
reference.document.write(<some string goes here>)
3.(From your third point)
As per understanding from your second point. You can create xml. So why are you changing after write the document?
Note: Generally XML is used for Server-to-server communication, JSON is used for Server-to-client(browser) communication.
Related
I want to write some data in an existing local XML file with Javascript with some text from an Html page. Is it possible to change content of nodes?
Here is XML sample:
<Notepad>
<Name>Player1</Name>
<Notes>text1</Notes>
</Notepad>
I will get some more text from input and want to add it after "text1", but can't find a solution.
function SaveNotes(content,player)
{
var xml = "serialize.xml";
var xmlTree = parseXml("<Notepad></Notepad>");
var str = xmlTree.createElement("Notes");
$(xmlTree).find("Notepad").find(player).append(str);
$(xmlTree).find("Notes").find(player).append(content);
var xmlString = (new XMLSerializer()).serializeToString(xmlTree);
}
Here is the code to manipulate xml content or xml file :
[Update]
Please check this Fiddle
var parseXml;
parseXml = function(xmlStr) {
return (new window.DOMParser()).parseFromString(xmlStr, "text/xml");
};
var xmlTree = parseXml("<root></root>");
function add_children(child_name, parent_name) {
str = xmlTree.createElement(child_name);
//strXML = parseXml(str);
$(xmlTree).find(parent_name).append(str);
$(xmlTree).find(child_name).append("hello");
var xmlString = (new XMLSerializer()).serializeToString(xmlTree);
alert(xmlString);
}
add_children("apple", "root");
add_children("orange", "root");
add_children("lychee", "root");
you can use it for searching in xml as well as adding new nodes with content in it. (And sorry i dont know how to load xml from client side and display it.)
but this fiddle demo will be helpful in adding content in xml and searching in it.
Hope it helps :)
If you want to achieve this on the client side you can parse your xml into a document object:
See
https://developer.mozilla.org/en-US/docs/Web/Guide/Parsing_and_serializing_XML
and
http://www.w3schools.com/xml/tryit.asp?filename=tryxml_parsertest2
And then manipulate it like you would the DOM of any html doc, e.g. createElement, appendChild etc.
See https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
Then to serialize it into a String again you could use https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
Persisting the data
Writing to a local file is not possible in a cross-browser way. In IE you could use ActiveX to read/write file.
You could use cookies to store data on the client side, if your data keeps small enough.
In HTML5 you could use local storage, see http://www.w3schools.com/html/html5_webstorage.asp
Try to use these two package one to convert to json and when is finish the other to come back
https://www.npmjs.com/package/xml2json
https://www.npmjs.com/package/js2xmlparser
I am requesting full HTML5 documents via Ajax using jQuery. I want to be able to parse them and transfer elements to my main page DOM, ideally with all major browsers, including mobile. I don't want to create an iframe as I want the process to be as quick as possible. With Chrome & Firefox I can do the following:
var contents = $(document.createElement('html'));
contents[0].innerHTML = data; // data : HTML document string
This will create a proper document, somewhat surprisingly, just without a doctype. In IE9, however, one may not use the innerHTML to set the contents of the html element. I tried to do the following, without any luck:
Create a DOM, open it, write to it and close it. Issue: on doc.open, IE9 throws an exception called Unspecified error..
var doc = document.implementation.createHTMLDocument('');
doc.open();
doc.write(data);
doc.close();
Create an ActiveX DOM. This time, the result is better but upon transferring / copying elements between documents IE9 crashes. Bad because no IE8 support (adoptNode / importNode support).
var doc = new ActiveXObject('htmlfile');
doc.open();
doc.write(data);
doc.close();
contents = $(doc.documentElement);
document.adoptNode(contents);
I was thinking about recursively recreating the elements, instead of transferring them between my documents, but that seems like an expensive task, given that I can have a lot nodes to transfer. I like my last ActiveX example as that will most likely work in IE8 and earlier (for parsing, at least).
Any ideas on this? Again, not only I need to be able to parse the head and body, but I also need to be able to append these new elements to my main dom.
Thanks much!
Answering my own question... To solve my issue I used all solutions mentioned in my post, with try/catch blocks if a browser throws an error (oh, how we love thee IE!). The following works in IE8, IE9, Chrome 23, Firefox 17, iOS 4 and 5, Android 3 & 4. I have not tested Android 2.1-2.3 and IE7.
var contents = $('');
try {
contents = $(document.createElement('html'));
contents[0].innerHTML = data;
}
catch(e) {
try {
var doc = document.implementation.createHTMLDocument('');
doc.open();
doc.write(data);
doc.close();
contents = $(doc.documentElement);
}
catch(e) {
var doc = new ActiveXObject('htmlfile');
doc.open();
doc.write(data);
doc.close();
contents = $(doc.documentElement);
}
}
At this point we can find elements using jQuery. Transferring them to a different DOM creates a bit of a problem. There are a couple of methods that do this, but they are not widely supported yet (importNode & adoptNode) and/or are buggy. Given that our selector string is called 'selector', below I re-created the found elements and append them to '.someDiv'.
var fnd = contents.find(selector);
if(fnd.length) {
var newSelection = $('');
fnd.each(function() {
var n = document.createElement(this.tagName);
var attr = $(this).prop('attributes');
n.innerHTML = this.innerHTML;
$.each(attr,function() { $(n).attr(this.name, this.value); });
newSelection.push(n);
});
$('.someDiv').append(newSelection);
};
I'm creating reporting from a SharePoint 2007 system via the provided WebServices on the client-side (this is all due to developer restrictions - I know, if I had permission, this entire exercise would be perfectly simple in SharePoint designer).
Currently I have a working report. In JavaScript I pass in three parameters (a "From" date, "To" date and "Business Category") which are used to generate a CAML query to web service. The XML response is returned and (after some formatting clean-up) an XSLT is imported (external file) and applied directly to it and the result is pumped into a DIV on the page. All works well.
At this point however I'd like to actually display the input parameters (dates and category) on the report. I have at least a few two kludgy options to do this:
1) Output the values outside of the display DIV. This will work but isn't very versitile.
2) Ouput place-holders for the values in the XSL and then run through a series of replacements before display. This just feels... odd.
3) Manually add nodes with the desired values to the XML packet before transformation then access them normally in the XSLT. This seems the cleanest to me... but also has some baggage I'm not sure I like.
Is there a "right" way to do this? Any chance one of those is it?
Here's some (abbreviated) code to illustrate:
// Set the URL of the XSL to apply
reportXSLURL = "BusinessCategoryReport.xsl";
// Set the input variables.
var CurCategory = DP_QueryString.get("ForCategory", "first");
var CurFrom = DP_QueryString.get("ForFrom", "first");
var CurTo = DP_QueryString.get("ForTo", "first");
* * Soap Call Censored (Too Hot for the Internet) * *
// Load the data
function ProcessResponse(ResponseText) {
// Create and load the serviceXML
var serviceXML = new DP_XML();
serviceXML.parse(ResponseText);
// Create and Load the XSL
var reportXSL = new DP_XML();
reportXSL.load(reportXSLURL);
// Clean Up
CleanSharePointColumn(serviceXML.Doc, "ows_Duration", "CalculatedField");
CleanSharePointColumn(serviceXML.Doc, "ows_Incident_x0020_Manager_x0028_s_x", "UserList");
CleanSharePointColumn(serviceXML.Doc, "ows_Application_x0020__x0028_EAI_x00", "LookupList");
CleanSharePointColumn(serviceXML.Doc, "ows_Business_x0020_Category", "LookupList");
CleanSharePointColumn(serviceXML.Doc, "ows_Incident_x0020_Start", "DateTime_Min");
CleanSharePointColumn(serviceXML.Doc, "ows_Incident_x0020_End", "DateTime_Min");
// Present the Results
document.getElementById("DataDisplay").innerHTML = serviceXML.Doc.transformNode(reportXSL.Doc);
};
You can pass parameters to an XSLT in javascript, just put
<xsl:param name="myparam" />
in the root of your stylesheet. Look into the setParameter method on the XSLTProcessor object in javascript. Here's a javascript method I use:
function transform(inputXml, xslt) {
var xsltProcessor;
var toReturn;
if (window.XSLTProcessor) {
xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xslt);
if (arguments.length > 2 && arguments.length % 2 == 0) {
for (var i = 0; i < Math.floor((arguments.length)/2)-1; i++) {
xsltProcessor.setParameter(null, arguments[2*i+2],arguments[2*i+3]);
}
}
toReturn = xsltProcessor.transformToDocument(inputXml);
}
else if (window.ActiveXObject) {
toReturn = makeDocFromString(inputXml.transformNode(xslt));
}
else {
toReturn = "Unable to transform";
}
return toReturn;
}
Any parameters beyond the first two are treated as name/value pairs to be passed to the xslt as a parameter. inputXml and xslt are both XML Documents.
EDIT: Just noticed, I forgot to mention this function uses a helper method, 'makeDocFromString', that just takes the source of an XML document as a string input, and returns an actual XML document. That function's define elsewhere in that .js, it's not part of the standard libraries.
I have a pdf document embedded inside a webpage in ASP.net and want to get a specific field inside the pdf document using Javascript...plain Javascript...
JavaScript in a PDF can call JS in a web page and visa versa, if BOTH are set up for it. You can see Acrobat's documentation here.
Check out the HostContainer specification, starting on page 486. In the PDF you'd need script something like:
var document = this; // hurray for closures.
this.hostContainer.messageHandler = { onDisclose: function() {return true;},
onMessage: function(msgArrayIgnored) {
// build a JSON string of field/value pairs
var outgoingMessage = "{ ";
for (var i = 0; i < this.numFields; ++i) {
var fldName = document.getNthFieldName(i);
var fld = document.getField(fld);
var val = fld.value;
// you'll probably need to escape 'val' to be legal JSON
outgoingMessage += fldName + ": \"" + val + "\";
// stick in a comma unless this is the last field
if (i != this.numFields-1) {
outgoingMessage += ", ";
}
}
outgoingMessage += "};";
this.hostContainer.postMessage( [outgoingMessage] );
};
In the HTML, you need to set up something similar. Lets assume your pdf is embedded in an object tag, and that element's id is "pdfElem". Your HTML script might look something like:
var pdf = document.getElementById("pdfElem");
pdf.messageHandler = function(message) {
var fldValPairs = eval(message);
doStuffWithFieldInfo(fldValPairs);
};
Later, any time you want to inspect the PDF's field info you post a message, and the PDF will call back to pdf.messageHandler with its JSON string wrapped in an array:
pdf.postMessage(["this string is ignored"]);
There's probably a bug or two lurking in there somewhere, but this will put you on the right track.
Webpage JavaScript will not be able to interact with the PDF form fields. You can however make a PDF form post to a web page form processor and then obtain the values in the form fields.
I am trying to write a report-generator to collect user-comments from a list of external HTML files. User-comments are wrapped in < span> elements.
Can this be done using JavaScript?
Here's my attempt:
function generateCommentReport()
{
var files = document.querySelectorAll('td a'); //Files to scan are links in an HTML table
var outputWindow = window.open(); //Output browser window for report
for(var i = 0; i<files.length; i++){
//Open each file in a browser window
win = window.open();
win.location.href = files[i].href;
//Scan opened window for 'comment's
comments = win.document.querySelectorAll('.comment');
for(var j=0;j<comments.length;j++){
//Add to output report
outputWindow.document.write(comment[i].innerHTML);
}
}
}
You will need to wait for onload on the target window before you can read content from its document.
Also what type of element is comment? In general you can't put a name on just any element. Whilst unknown attributes like a misplaced name may be ignored, you can't guarantee that browsers will take account of them for getElementsByName. (In reality, most browsers do, but IE doesn't.) A class might be a better bet?
Each web browse works in a defined and controlled work space on a user computer where certain things are restrict to code like file system - these are safety standards to ensure that no malicious code from internet runs into your system to phishing sensitive information stored on in it. Only ways a webbrowser is allowed if access granted explicitly by the user.
But i can suggest you for Internet Application as
- If List of commands is static then cache either by XML, Json or Cookies [it will store on user's system until it expires]
- If dynamic then Ajax to retrieve it
I think I have the solution to this.
var windows = [];
var report = null;
function handlerFunctionFactory(i,max){
return function (evt){
//Scan opened window for 'comment's
var comments = windows[i].document.querySelectorAll('.comment');
for(var j=0;j<comments.length;j++){
//Add to output report
report.document.write(comments[j].innerHTML);
}
if((i+1)==max){
report.document.write("</div></body></html>");
report.document.close();
}
windows[i].close();
}
}
function generateReport()
{
var files = document.querySelectorAll('td a'); //The list of files to scan is stored as links in an HTML table
report = window.open(); //Output browser window for report
report.title = 'Comment Report';
report.document.open();
report.document.write('<!DOCTYPE html PUBLIC"-// W3C//DTD XHTML 1.0 Transitional//EN"" http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
+ '<html><head><title>Comment Report</title>'
+ '</head><body>');
for(var i = 0; i<files.length; i++){
//Open each file in a browser window
win = window.open();
windows.push(win)
win.location.href = files[i].href;
win.onload = handlerFunctionFactory(i,files.length);
}
}
Any refactoring tips are welcome. I am not entirely convinced that factory is the best way to bind the onload handlers to an instance for example.
This works only on Firefox :(