Jquery suddenly stopped parsing xml - javascript

For some browsers, for some clients, jquery suddenly stopped parsing xml.
Example xml:
<?xml version="1.0" encoding="UTF-8"?>
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:example_namespace="https://mylink.com/wfs/example_namespace" xsi:schemaLocation="https://mylink.com/wfs/example_namespace mylink.com?SERVICE=WFS&VERSION=1.0.0&TYPENAME=example_namespace:TABLE&REQUEST=DescribeFeatureType" numberMatched="unknown" numberReturned="1">
<gml:featureMember>
<example_namespace:TABLE fid="TABLE.15">
<example_namespace:ID>15</example_namespace:ID>
</example_namespace:TABLE>
</gml:featureMember>
</wfs:FeatureCollection>
Example jquery
$.get(link, function(data) { //Response is xml like in example.
console.log(data) //works as before
console.log($(data).find("featureMember").find("ID").text())
//Doesn't work now for some clients, but worked before.
})
EDIT:
More general example:
XML
<?xml version="1.0" encoding="UTF-8"?>
<a xmlns:c="http://www.example.com">
<c:b>TEST</c:b>
</a>
AND JS:
console.log($(data).find("b").text())
now returns: "", before returns: "TEST"
EDIT 2:
Similar problem:
Cannot extract SOAP XML with jQuery
This code was originally working in Chrome last week and once Chrome
updated to v60 it no longer does.

Pass data to $.parseXML() to get a #document, use .querySelector()
$.parseXML(data).querySelector("featureMember").querySelector("ID").textContent;
alternatively pass result of $.parseXML() to jQuery() and use .find()
$($.parseXML(data)).find("featureMember").find("ID").text();
jsfiddle https://jsfiddle.net/5fuLquth/

Parsing XML using jQuery in this way has some browser compatibility bugs I believe. This has been a won't fix jquery bug previously.
When there are namespaces in the xml you can use jquery selectors like the below by escaping the colon:
.find('gml\\:featureMember')
or using nodeName:
.find('[nodeName="gml:featureMember"]')
See demo below:
var xml=`<?xml version="1.0" encoding="UTF-8"?><wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:example_namespace="https://mylink.com/wfs/example_namespace" xsi:schemaLocation="https://mylink.com/wfs/example_namespace mylink.com?SERVICE=WFS&VERSION=1.0.0&TYPENAME=example_namespace:TABLE&REQUEST=DescribeFeatureType" numberMatched="unknown" numberReturned="1"><gml:featureMember><example_namespace:TABLE fid="TABLE.15"><example_namespace:ID>15</example_namespace:ID></example_namespace:TABLE></gml:featureMember></wfs:FeatureCollection>`;
console.log($(xml)
.find('gml\\:featureMember')
.find("example_namespace\\:ID").text());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

Xpages dojo charting breaking csjs

I just started using The Dojo charting feature in Xpages. After following this tutorial by Andrew Champion. I Found that the simple csjs script to create a pie chart does not work. It breaks on the creation of the Pie Chart in CSJS. Using most basic code for better readability.
makeCharts = function()
{
alert("test");
var pieChart = new dojox.charting.Chart2D("#{id:panel1}");
};
The alert in the code above does not run when I call the function in my Xpage. I Followed the tutorial exactly but had no results. Any help would be appreciated.
Xpage source code below:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" dojoParseOnLoad="true"
dojoTheme="true">
<xp:this.resources>
<xp:dojoModule name="dojox.charting.Chart2D"></xp:dojoModule>
<xp:script src="/scriptsChartDojo.jss" clientSide="false"></xp:script>
<xp:script src="/scriptsChartDojoCSJS.js" clientSide="true"></xp:script>
</xp:this.resources>
<xp:scriptBlock id="scriptBlock1"
value="XSP.addOnLoad(makeCharts);">
</xp:scriptBlock>
<xp:panel style="height:450px;width:450px" id="panel1">
</xp:panel>
</xp:view>
I don't think you can include server generated code in js files. If you open the scriptsChartDojoCSJS.js file in your browser, you will see that #{id:panel1} has not been altered.
Instead you can add the makeCharts function to your xp:scriptBlock.

javascript code in XSLT

I'm using XSLT to transform an XML into HTML on the client side (Chrome browser).
I'm trying to add <script> HTML tag to the XSLT but it seems that the code in it is never evaluated on the generated HTML, although I've specified defer.
On the other hand, onclick event itself runs OK.
Here is an example of the XSLT which demonstrates the issue:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"
encoding="UTF-8"
indent="no"/>
<xsl:template match="/">
<html>
<head>
<script type="text/javascript" defer="defer">
<xsl:text>
<![CDATA[
function test(){
window.alert('Test');
}
]]>
</xsl:text>
</script>
</head>
<body>
<button onclick="window.alert('Test')">This works</button>
<br/>
<button onclick="test()">This does not work</button>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
The XML file does not matter is this example. You can try the above example on W3Schools online XSLT transformation
In this example, clicking on This does not work yields an error: Uncaught ReferenceError: test is not defined.
What am I doing wrong here?
Update
The problem only happens when I'm performing the XSLT transformation itself in javascript. Here is the piece of code that is doing that in my case:
var processor = new XSLTProcessor(),
htmlResult;
processor.importStylesheet(xsl);
htmlResult = processor.transformToFragment(xhr.responseXML, document);
document.getElementById("result").appendChild(htmlResult);
Update
I also need the following to work correctly when they appear in the XSLT file:
Loading external javascript files using script element:
<script type="text/javascript" src="/somelibrary.js" />
Bare <script> elements with javascript code in them, that call functions which are declared in an external javascript file, loaded by an earlier script element.
As far as I have researched, this is a known bug in Chrome reported in 2013 in https://code.google.com/p/chromium/issues/detail?id=266305. It does not look as any effort has been taken to fix it. However, the bug reporter also found a workaround, instead of using appendChild or insertBefore or similar to insert the fragment returned by transformToFragment directly into the document, if you call importNode first on the fragment, the script elements are then executed when you insert the imported fragment into the document.
I have written a test case http://home.arcor.de/martin.honnen/xslt/test2015111606.html which works fine for me a current version of Chrome on Windows, it uses
var proc = new XSLTProcessor();
proc.importStylesheet(xsltDoc);
targetElement.appendChild(targetElement.ownerDocument.importNode(proc.transformToFragment(xmlDoc, targetElement.ownerDocument), true));
However, do note that Microsoft Edge neither with the normal approach of calling appendChild on the fragment nor with the above Chrome workaround executes the script element's code.
Possible solution: (inspired from this answer)
function insertAndExecute(id, htmlResult) {
document.getElementById(id).appendChild(htmlResult);
var scripts = document.getElementById(id).getElementsByTagName("script");
var deferreds = [];
// First load all external scripts
for (var i = 0; i < scripts.length; i++) {
if (scripts[i].src != "") {
deferreds.push($.getScript(scripts[i].src));
}
}
// Execute other (inline) scripts after all external scripts are loaded
$.when.apply(null, deferreds).done(function() {
for (var i = 0; i < scripts.length; i++) {
if (!scripts[i].src) {
$.globalEval(scripts[i].innerText || scripts[i].textContent);
}
}
})
}
var processor = new XSLTProcessor(),
htmlResult;
processor.importStylesheet(xsl);
htmlResult = processor.transformToFragment(xhr.responseXML, document);
// The htmlResult may contain javascript code. Scan and run it
insertAndExecute("result", htmlResult);

Firebreath function call

I am trying to call firebreath functions from my javascript file.Everything works fine if I call the firebreath functions using an html document with javascript functions and also for firefox version upto 28. For higher versions of firefox on calling the functions through plugin I get an error "TypeError:plugin.echo is not a function" (echo is an inbuilt firebreath function). Find the below code for reference.
overlay.xul
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/"?>
<overlay id="mypluginOverlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
<script type="application/x-javascript" src="chrome://myplugin/content/ngContent.js"/>
<vbox style="height:0;">
<html:object type="application/x-myplugin" id="myplugin" style="height:0;"></html:object>
</vbox>
</overlay>
ngContent.js
try
{
var plugin = document.getElementById('myplugin');
alert(plugin); // Output for firefox version upto 28 : <JSAPI-Auto Javascript Object>
//Output for firefox higher versions : [object HTMLObjectElement]
plugin.echo("qwerty");
}
catch(ErrorMessage)
{
alert(ErrorMessage);
}
Can anyone help me in this??? Thanks in advance....
EDIT:
Tried html:embed tag instead of html:object in overlay.xul.
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/"?>
<overlay id="mypluginOverlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
<script type="application/x-javascript" src="chrome://myplugin/content/ngContent.js"/>
<vbox style="height:0;">
<html:embed type="application/x-myplugin" id="myplugin" style="height:0;"></html:embed>
</vbox>
</overlay>
It doesn't work either.

Sorting XML file via XSLT and JavaScript

I am currently trying to implement a function to sort a XML file by the attribute of one of its nodes.
The way to go seemed to be using XSLT to transform the XML file and by researching a bit I managed to put together a working XSLT file (validated in some online-validator, output was as would be expected).
After I got the results I wanted, I started implementing JavaScript functions to do this automatically every time it is required. Ultimately a chart (amCharts) will be created using the data from the XML file. To generate that chart properly, the data has to be sorted though.
Right now everything seems to work syntax-wise, however, the XSLTProcessor and/or XMLSerializer seem to have problems parsing/combining both the XML and XLST file.
Strangely enough Firefox also throws an error: Component returned failure code: 0x80600001 [nsIXSLTProcessor.importStylesheet]
Chrome doesn't seem to have this problem.
But this is not the main issue. The result generated contains a rudimental HTML page saying that there was an error, but giving no exact error description/location/explanation whatsoever.
I expected to see the sorted XML file here, just as in the online XML/XSLT validator, which had the same inputs XML/XSLT content wise.
Does anyone have an idea regarding the source of this issue? Would greatly appreciate any hints and/or solutions to this.
best regards,
daZza
Edit
After researching the "Extra content at the end of the document" error on the generated page more in-depth (and having overlooked it when I posted the OP), it seems that the error is triggered when there are more than one root elements in the XML file, which would obviously be wrong.
However, the source XML files do not have multiple root nodes and are all perfectly valid.
This leads me to believe that the XSLT reordering/sorting of the source file is not done as expected, although it looked good in the XSLT validator.
I guess somehow it produces multiple root nodes instead of just reordering the item nodes within the root node?
Unfortunately I am no expert regarding XSLT so it would be awesome, if someone with a more detailed knowledge could especially look at the XSLT code.
Edit2
I think I might have solved the problem by changing the XSLT query slightly. I am getting a proper looking output for Chrome and Firefox, but IE still throws an error (did I mention that I hate cross-browser compatibilities? -.-).
Further testing is still required, but at least it's a progress. Still appreciating any hints regarding the topic though.
Code:
XML Sample Snippet (removed content, the "" parts are filled in the real file):
<?xml version="1.0" encoding="utf-8"?>
<root>
<item Art="" LinkTitle="" Eindruck="" Bereich="" Unterbereich="" Priority="" Handlungsma_x00df_nahme="" Status_x0020_der_x0020_Ma_x00df_="" Aufwand="" Benefit="" Termin_x0020_der_x0020_Retrospek="" Produkt="" Release="" />
<item Art="" LinkTitle="" Eindruck="" Bereich="" Unterbereich="" Priority="" Handlungsma_x00df_nahme="" Status_x0020_der_x0020_Ma_x00df_="" Aufwand="" Benefit="" Termin_x0020_der_x0020_Retrospek="" Produkt="" Release="" />
</root>
XSLT file
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:choose>
<xsl:when test="*[local-name()='item']">
<xsl:apply-templates select="#* | node()">
<xsl:sort select="#Unterbereich" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="#* | node()" />
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
JavaScript function
function sortXML()
{
var parser = new DOMParser();
// xml and xsl are correctly filled with the data from their appropriate files
// via AJAX GET requests earlier in the code
var domToBeTransformed = xml;
var xslt = xsl;
var processor = new XSLTProcessor();
processor.importStylesheet(xslt);
var newDocument = processor.transformToDocument(domToBeTransformed);
var serializer = new XMLSerializer();
var newDocumentXml = serializer.serializeToString(newDocument);
alert(newDocumentXml);
}
Currently generated document (var newDocumentXml)
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<parsererror style="display: block; white-space: pre; border: 2px solid #c77; padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color: black">
<h3>This page contains the following errors:</h3>
<div style="font-family:monospace;font-size:12px">error on line 1 at column 1: Extra content at the end of the document</div>
<h3>Below is a rendering of the page up to the first error.</h3>
</parsererror>
</body>
</html>
Firstly, I would re-jig your XSLT to avoid the use of xsl:choose. There is no point in testing if a child element exists if you are already matching an attribute or text node. It may be better (and cleaner, with less indentation) to use separate templates.
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[*[local-name()='item']]">
<xsl:copy>
<xsl:apply-templates select="#*" />
<xsl:apply-templates select="node()">
<xsl:sort select="#Unterbereich" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
The first thing to note is that you specified a version of "2.0" in your XSLT. Microsoft (and so IE) does not natively support XSLT 2.0. However, in this case, you are not using any XSLT 2.0 features, so changing it to XSLT 1.0 should not be a problem (Of course, if your actual XSLT does need to use 2.0, then that is a whole separate question!)
But I don't think this is an issue with your XSLT any more, but more an issue with how transformation is done in the browser with javascript. The code you have given will only work in Chrome and Firefox (and Opera, I think). IE doesn't support those commands, and has its own methods. And to compound matters further, IE10 and above do things differently to previous versions!
Anyway, I headed over to Object doesn't support property or method 'transformNode' in Internet Explorer 10 (Windows 8) and found a good sample of JavaScript. Try re-jigging your JavaScript to this:
function sortXML()
{
if (typeof (XSLTProcessor) != "undefined")
{
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
var resultDocument = xsltProcessor.transformToDocument(xml);
var serializer = new XMLSerializer();
var newDocumentXml = serializer.serializeToString(resultDocument);
alert(newDocumentXml);
}
else if (typeof (xml.transformNode) != "undefined")
{
var ex = xml.transformNode(xsl);
alert(ex);
}
else
{
var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
xslDoc.load(xsl);
var xslt = new ActiveXObject("Msxml2.XSLTemplate");
xslt.stylesheet = xslDoc;
var xslProc = xslt.createProcessor();
xslProc.input = xml;
xslProc.transform();
alert(xslProc.output);
}
}

XSL parsing is shortening script tag causing issues in IE

I have a C# application that generates an html document from transforming an xml file with an xsl file. In my xsl template I reference an external javascript file like this:
<script language="javascript" type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js" ></script>
after the transformation the previous line is being translated to:
<script language="javascript" type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js" />
For Firefox and Chrome this is no problem however IE throws an 'object not found' error and does not work. Any suggestions for getting IE to like this syntax? Or is there something I need to do in my xsl (or the C# XslCompiledTransform class) to preserve the syntax?
Solution: By placing <![CDATA[ <!-- Some Comment --> ]]> between the script tags the parser doesn't attempt to shorten the ending tag.
Try putting an empty CDATA section inside. This should force the parser to not mess with your script tags.
<script language="javascript" type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js" ><![CDATA[ ]]></script>
Actually, bobince is right. If you use...
<xsl:output method="html"/>
... you can get the right output for XslCompiledTransform, but you have to use its OutputSettings with the XmlWriter you use as output object:
XslCompiledTransform xslt = new XslCompiledTransform(true);
xslt.Load("stylesheetFile.xsl");
XmlWriter outputWriter = XmlWriter.Create("outputfile.html", xslt.OutputSettings);
xslt.Transform(input, null, outputWriter);
This way, the method="html" works, so script, textarea et al keep their closing tags.
Generate an XML comment inside <script>:
<script type="text/javascript" src="..." ><xsl:comment/></script>
The output will be:
<script type="text/javascript" src="..."><!-- --></script>
which is semantically equivalent to an empty <script>.
Not preserve it, but if you're producing backwards-compatible HTML you need to tell the XSLT processor that HTML-compatible-XHTML is what you want and not generic self-closing-allowed XML:
<xsl:output method="xhtml"/>
Unfortunately, the ‘xhtml’ output method is an XSLT 2.0 extension that .NET's XslTransform doesn't support, so you have to use good old legacy HTML instead:
<xsl:output method="html"/>
(and appropriate HTML 4.01 DOCTYPE instead of XHTML.)
Putting some dummy content in <script> may solve your immediate problem, but there may be other places where the default ‘xml’ output method will produce inappropriate markup for legacy browsers like IE.
Re: comment. Hmm... you're right! The ‘html’ output method does not produce valid HTML; the ‘xhtml’ output method does not produce XHTML conformant to XHTML Appendix C. What's more, ‘html’ includes provisions such as not escaping ‘<’, and de-escaping the ancient and broken-even-for-its-time Netscape 4 construct ‘&{...}’, that will take your working markup and make it invalid.
So changing the output method is completely useless, and the only way to produce working HTML with XSLT is:
a. hack every occurrence of an inappropriate self-closing tag manually (there are likely to be many more than just this script), or
b. post-process with something like HTMLTidy.
How sad, and sloppy that this hasn't been addressed even in XSLT 2.0.
had the same prob. right now, this is my solution:
<xsl:text disable-output-escaping="yes">
<![CDATA[<script type="text/javascript" src="" ></script>]]>
</xsl:text>
Just Missing the closing </script>.
<xsl:output method="html" omit-xml-declaration="yes" doctype-system="about:legacy-compat" encoding="utf-8"/>
should solve your probleme

Categories

Resources