Created
October 14, 2018 10:51
-
-
Save aliaspooryorik/fbd657962d0f4576af33c0fce7e9f072 to your computer and use it in GitHub Desktop.
parsing XML doc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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