问题
I am using ColdFusion 8.
I am parsing an XML document and need to get at a single value that is buried deep in the document. I am successfully parsing the document and getting the values I need, but it seems that there has to be a more efficient means to get to the same data.
I have NOT parsed much XML. Is having to test for the existence of keys this deep very typical in parsing XML or am I doing something wrong? Is there a better way to code this?
// PARSE THE SOAP RESPONSE
SoapResponse = xmlParse(httpResponse.fileContent);
// PUT THE RESPONSE NODES INTO AN ARRAY
ResponseNodes = xmlSearch(SoapResponse, "//*[ local-name() = 'OnlineBoothInformation' ]");
// LOOP THROUGH THE ARRAY AND GET EACH NODE
for (i = 1; i lte arrayLen(ResponseNodes); i++) {
// CREATE NEW STRUCTURE TO HOLD BOOTH DATA
BoothInfo = structNew();
// TEST FOR CUSTOM FIELDS TO FIND NEW EXHIBITOR
BoothInfo.NewExhibitor = 0; // DEFAULT NEW EXHIBITOR
if (structKeyExists(ResponseNodes[i], "CustomFields")) {
CustomFields = xmlParse(ResponseNodes[i].CustomFields);
for (j = 1; j lte arrayLen(CustomFields); j=j+1) {
if (structKeyExists(ResponseNodes[i].CustomFields[j], "Field")) {
Field = xmlParse(ResponseNodes[i].CustomFields[j].Field);
for (k = 1; k lte arrayLen(Field); k=k+1) {
if (ResponseNodes[i].CustomFields[j].Field[k].XmlAttributes.Name == "New Exhibitor") {
BoothInfo.NewExhibitor = 1;
}
}
}
}
}
}
I am getting other values for the BoothInfo structure. They were MUCH easier to get at. I did not include them in this example.
UPDATE
I was able to rewrite the code and get at what I needed much more efficiently.
// NEW EXHIBITOR
BoothInfo.NewExhibitor = 0;
if (structKeyExists(ResponseNodes[i].CustomFields, "Field")) {
Fields = ResponseNodes[i].CustomFields.Field;
for (j = 1; j lte arrayLen(Fields); j++) {
if (Fields[j].XmlAttributes.Name == "New Exhibitor") {
BoothInfo.NewExhibitor = 1;
break;
}
}
}
回答1:
Well, I don't see why you're calling xmlParse over and over. You use that to convert a string to an XML nodeset, but you already have an XML nodeset.
You can use a more specific XPath specification for the nodes you want. Maybe something like, //*[ local-name() = 'OnlineBoothInformation' ]/CustomFields/Field[@Name="New Exhibitor"]. Then you can just check whether an empty array was returned. XPath is really expressive, but it takes some getting used to. Take care that while CF is generally not case-sensitive, XPath is. I copied the case from your CF, but that has to match the case in the XML in order to work.
来源:https://stackoverflow.com/questions/9710703/how-to-efficiently-test-and-parse-a-deep-value-in-xml