Javascript to add cdata section on the fly?
I'm having trouble with special characters that exist in an xml node attribute. To combat this, I'm trying to render the attributes as child nodes and, where necessary, using cdata sections to get around the special characters. The problem is, I can't seem to get the cdata section appended to the node correctly.
I'm iterating over the source xml node's attributes and creating new nodes. If the attribute.name = "description" I want to put the attribute.text() in a cdata section and append the new node. That's where I jump the track.
// newXMLData is the new xml document that I've created in memory
for (var ctr =0;ctr< this.attributes.length;ctr++){ // iterate over the attributes
if( this.attributes[ctr].name =="Description"){ // if the attribute name is "Description" add a CDATA section
var thisNodeName = this.attributes[ctr].name;
newXMLDataNode.append("<"+thisNodeName +"></"+ thisNodeName +">" );
var cdata = newXMLData.createCDATASection('test'); // here's where it breaks.
} else {
// It's not "Description" so just append the new node.
newXMLDataNode.append("<"+ this.attributes[ctr].name +">" + $(this.attributes[ctr]).text() + "</"+ this.attributes[ctr].name +">" );
}
}
开发者_高级运维Any ideas? Is there another way to add a cdata section?
Here's a sample snippet of the source...
<row
pSiteID="4"
pSiteTile="Test Site Name "
pSiteURL="http://www.cnn.com"
ID="1"
Description="<div>blah blah blah since June 2007.&nbsp; T<br>&nbsp;<br>blah blah blah blah&nbsp; </div>"
CreatedDate="2010-09-20 14:46:18"
Comments="Comments example. " >
here's what I'm trying to create...
<Site>
<PSITEID>4</PSITEID>
<PSITETILE>Test Site Name</PSITETILE>
<PSITEURL>http://www.cnn.com</PSITEURL>
<ID>1</ID>
<DESCRIPTION><![CDATA[<div>blah blah blah since June 2007.&nbsp; T<br>&nbsp;<br>blah blah blah blah&nbsp; </div ]]></DESCRIPTION>
<CREATEDDATE>2010-09-20 14:46:18</CREATEDDATE>
<COMMENTS><![CDATA[ Comments example. ]]></COMMENTS>
</Site>
I had the same issue. i was trying to append CDATA to xml nodes, so i thought its as easy as adding like so:
valueNode[0].text = "<![CDATA["+ tmpVal +"]]>";
//valueNode[0] represents "<value></value>"
This does not work because the whole thing will get interpreted as text therefore <(less than) and > (great than) will be replaced automatically.
what you need to do is use createCDATASection by doing the following:
var tmpCdata = $xmlDoc[0].createCDATASection(escape("muzi test 002"));
//i'm also escaping special charactures as well
valueNode[0].appendChild(tmpCdata);
results will be:
<value><![CDATA[muzi%20test%20002]]></value>
Brettz9 (in previous answer) explains how to do this but quite complex, therefore i just wanted to add my solution which is much simpler.
thanks,
Not sure of browser support for document.implementation.createDocument or createCDataSection, but this works in Mozilla at least:
<script>
// Define some helpers (not available IE < 9)
function parse (str) {
return new DOMParser().parseFromString(str, 'text/xml').documentElement;
}
function ser (dom) {
return new XMLSerializer().serializeToString(dom);
}
// Simulate your XML retrieval
var row = '<row pSiteID="4" pSiteTile="Test Site Name " pSiteURL="http://www.cnn.com" ID="1" Description="<div>blah blah blah since June 2007.&nbsp; T<br>&nbsp;<br>blah blah blah blah&nbsp; </div>" CreatedDate="2010-09-20 14:46:18" Comments="Comments example. " />';
// Hack to convert source to well-formed XML, or otherwise you can't use DOM methods on it which
// depend on well-formed XML
row = row.replace(/(=\s*")([\s\S]*?)(")/g, function (n0, n1, n2, n3) {
return n1+ // Add back equal sign and opening quote
n2.replace(/</g, '<'). // Create well-formed XML by avoiding less-than signs inside attributes
replace(/&nbsp;/g, '&#160;')+ // HTML entities (except for gt, lt, amp, quot) must be either converted to numeric character references or your XML must define the same entities
n3; // Add back closing quote
});
// Simulate your retrieval of DOM attributes, though in this context, we're just making attributes into a global
this.attributes = parse(row).attributes;
// Simulate your creation of an XML document
var newXMLData = document.implementation.createDocument(null, 'Site', null);
// Modify your code to avoid jQuery dependency for easier testing and to
// avoid confusion (error?) of having two variables, newXMLData and newXMLDataNode
for (var ctr =0;ctr< this.attributes.length;ctr++){ // iterate over the attributes
if (this.attributes[ctr].name =="Description") { // if the attribute name is "Description" add a CDATA section
var thisNodeName = this.attributes[ctr].name;
var str = "<"+thisNodeName +"></"+ thisNodeName +">";
var node = parse(str);
var cdata = newXMLData.createCDATASection(this.attributes[ctr].textContent);
node.appendChild(cdata);
newXMLData.documentElement.appendChild(node);
}
else {
// It's not "Description" so just append the new node.
var str= "<"+ this.attributes[ctr].name +">" + this.attributes[ctr].textContent + "</"+ this.attributes[ctr].name +">";
newXMLData.documentElement.appendChild(parse(str));
}
}
// Prove its working (though you may wish to use toUpperCase() if you need the element names upper-cased);
// if you need CDATA for Comments, you can follow the pattern above to add support for that too
alert(ser(newXMLData));
</script>
精彩评论