Skip to content

Instantly share code, notes, and snippets.

@aliaspooryorik
Created October 14, 2018 10:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aliaspooryorik/fbd657962d0f4576af33c0fce7e9f072 to your computer and use it in GitHub Desktop.
Save aliaspooryorik/fbd657962d0f4576af33c0fce7e9f072 to your computer and use it in GitHub Desktop.
parsing XML doc
<cfscript>
// asked in cfml slack #cfml-beginners
function getNodePaths(xmldoc) {
var nodes = extractTextNodes(xmldoc);
var xPaths = [];
for (var node in nodes) {
xPaths.append(getXPath(node));
}
return xPaths;
}
function extractTextNodes(xmldoc) {
return xmlSearch(xmldoc, "//*[not(*)]");
}
function getXPath(node) {
var path = getHierarchy(node);
return path.toList('.');
}
xmldoc = getXML();
arr = getNodePaths(xmldoc);
writeDump(arr);
function xmlToStruct(xmldoc) {
var nodes = extractTextNodes(xmldoc);
var result = {};
for (var node in nodes) {
var map = nodeAsMap(node);
structAppend(result, map);
}
return result;
}
function nodeAsMap(node) {
var value = node.getTextContent();
var path = getXPath(node);
var result = {
"#path#": value
};
return result;
}
function getHierarchy(node) {
var path = [];
while(!isNull(node.getParentNode())) {
path.insertAt(1, node.getNodeName());
node = node.getParentNode();
}
return path;
}
map = xmlToStruct(xmldoc);
writeDump(map);
</cfscript>
<cffunction name="getXML" output="false">
<cfsavecontent variable="ink">
<createTransactionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
<merchantAuthentication>
<name>8Tsa42UJ</name>
<transactionKey>7NDT76Fhf85fq62t</transactionKey>
</merchantAuthentication>
<refId>123456</refId>
<transactionRequest>
<transactionType>authCaptureTransaction</transactionType>
<amount>5</amount>
<payment>
<creditCard>
<cardNumber>5424000000000015</cardNumber>
<expirationDate>2020-12</expirationDate>
<cardCode>999</cardCode>
</creditCard>
</payment>
<order>
<invoiceNumber>INV-12345</invoiceNumber>
<description>Product Description</description>
</order>
<lineItems>
<lineItem>
<itemId>1</itemId>
<name>vase</name>
<description>Cannes logo </description>
<quantity>18</quantity>
<unitPrice>45.00</unitPrice>
</lineItem>
</lineItems>
<tax>
<amount>4.26</amount>
<name>level2 tax name</name>
<description>level2 tax</description>
</tax>
<duty>
<amount>8.55</amount>
<name>duty name</name>
<description>duty description</description>
</duty>
<shipping>
<amount>4.26</amount>
<name>level2 tax name</name>
<description>level2 tax</description>
</shipping>
<poNumber>456654</poNumber>
<customer>
<id>99999456654</id>
</customer>
<billTo>
<firstName>Ellen</firstName>
<lastName>Johnson</lastName>
<company>Souveniropolis</company>
<address>14 Main Street</address>
<city>Pecan Springs</city>
<state>TX</state>
<zip>44628</zip>
<country>USA</country>
</billTo>
<shipTo>
<firstName>China</firstName>
<lastName>Bayles</lastName>
<company>Thyme for Tea</company>
<address>12 Main Street</address>
<city>Pecan Springs</city>
<state>TX</state>
<zip>44628</zip>
<country>USA</country>
</shipTo>
<customerIP>192.168.1.1</customerIP>
<userFields>
<userField>
<name>MerchantDefinedFieldName1</name>
<value>MerchantDefinedFieldValue1</value>
</userField>
<userField>
<name>favorite_color</name>
<value>blue</value>
</userField>
</userFields>
</transactionRequest>
</createTransactionRequest>
</cfsavecontent>
<cfreturn XMLparse(trim(ink))>
</cffunction>
<!---
<cffunction name="xmlToCF" hint="Takes an XML object and converts it into an equivalent CF object" access="public" output="no" returntype="any">
<cfargument name="thexml" type="XML" required="Yes">
<!--- Only supports use of attributes if the element is unique to the parent node --->
<cfset var x = structnew()>
<cfset var i = "">
<cfset var a = "">
<cfset var n = "">
<cftry>
<cfscript>
if(len(structkeylist(thexml))) {
for(i in thexml) {
if (arraylen(thexml[i]) gt 1) {
x = arraynew(1);
for(n = 1; n lte arraylen(thexml[i]); n = n + 1) {
x[n] = xmlToCF(duplicate(thexml[i][n]));
}
}
else if(len(structkeylist(thexml[i]))) {
x[i] = xmlToCF(duplicate(thexml[i]));
}
else {
if(len(structkeylist(thexml[i]['xmlattributes']))) {
x[i] = structnew();
x[i].value = thexml[i].xmltext;
for(a in thexml[i].xmlattributes) {
x[i][a] = thexml[i]['xmlattributes'][a];
}
}
else {
x[i] = thexml[i].xmltext;
}
}
}
}
return x;
</cfscript>
<cfcatch>
<cfrethrow>
</cfcatch>
</cftry>
</cffunction>
<cffunction name="flattenStruct" hint="returns struct containing paths and values" access="public" output="no" returntype="struct">
<cfargument name="object" type="struct" required="yes">
<cfargument name="forcecase" type="string" required="no" default="natural"><!--- lower, upper, natural --->
<cfset var data = structnew()>
<cfset var x = "">
<cfset var c = "">
<cfset var a = "">
<cfset var p = "">
<cfset var path = "">
<cfset var z = 0>
<cftry>
<cfscript>
if(structkeyexists(arguments,"parentnode")) {
path = listappend(path,arguments.parentnode,".");
}
for(c in arguments.object) {
if(issimplevalue(arguments.object[c])) {
p = listappend(path,c,".");
if(arguments.forcecase eq "lower") {
p = lcase(p);
}
else if(arguments.forcecase eq "upper") {
p = ucase(p);
}
data[p] = arguments.object[c];
}
else if(isarray(arguments.object[c])) {
z = 0;
for(a in arguments.object[c]) {
z++;
if(isstruct(a)) {
structappend(data,flattenStruct(object=a,forcecase=arguments.forcecase,parentnode=listappend(path,c & "_" & z,".")));
}
else {
p = listappend(path,c & "_" & z,".");
if(arguments.forcecase eq "lower") {
p = lcase(p);
}
else if(arguments.forcecase eq "upper") {
p = ucase(p);
}
data[p] = serializejson(arguments.object[c]);
}
}
}
else if(isstruct(arguments.object[c]) and not structisempty(arguments.object[c])) {
structappend(data,flattenStruct(object=arguments.object[c],forcecase=arguments.forcecase,parentnode=listappend(path,c,".")));
}
}
return data;
</cfscript>
<cfcatch>
<cfrethrow>
</cfcatch>
</cftry>
</cffunction>
<cfscript>
thestruct = xmlToCF(xmlParse(ink));
writedump(flattenStruct(thestruct));
</cfscript>
<cfset myStructure = flattenStruct(thestruct)>
<cfset lst = ''>
<cfloop collection="#myStructure#" item="key">
<cfset lst = listappend(lst,'<cfargument name="#key#" default="" type="any">')>
</cfloop>
<cfdump var="#lst#">
--->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment