问题
I'm new to XML and we need to do GeoCoding with the new Bing Spatial Data API. I've managed to get a result back from them in xml format. How would I read specific elements in the response, ie. the Link, Status and ErrorMessages?
<?xml version="1.0" encoding="utf-8"?>
<Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/search/local/ws/rest/v1">
<Copyright>Copyright © 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.</Copyright>
<BrandLogoUri>http://spatial.virtualearth.net/Branding/logo_powered_by.png</BrandLogoUri>
<StatusCode>201</StatusCode>
<StatusDescription>Created</StatusDescription>
<AuthenticationResultCode>ValidCredentials</AuthenticationResultCode>
<TraceId>ID|02.00.82.2300|</TraceId>
<ResourceSets>
<ResourceSet>
<EstimatedTotal>1</EstimatedTotal>
<Resources>
<DataflowJob>
<Id>ID</Id>
<Link role="self">https://spatial.virtualearth.net/REST/v1/dataflows/Geocode/ID</Link>
<Status>Pending</Status>
<CreatedDate>2011-03-30T08:03:09.3551157-07:00</CreatedDate>
<CompletedDate xsi:nil="true" />
<TotalEntityCount>0</TotalEntityCount>
<ProcessedEntityCount>0</ProcessedEntityCount>
<FailedEntityCount>0</FailedEntityCount>
</DataflowJob>
</Resources>
</ResourceSet>
</ResourceSets>
</Response>
I'm using Delphi XE.
Regards, Pieter
回答1:
How about using some simple XPATH to get the requested values?
//Link[1]/node()
- selects the first "Link" node from the whole document, and then selects the first child node of any kind. It just happens that the first child node is the unnamed node containing the actual https
link.
Assuming the XML document is loaded into Doc: TXMLDocument
, you can extract the Link with this code:
(Doc.DOMDocument as IDomNodeSelect).selectNode('//Link[1]/node()').nodeValue
You can find some documentation about XPath reading those XPath Examples on MSDN. You might find better documentation at w3schools. And to top it all up, here's a simple (but complete) console application that uses XPath to extract and display the 3 requested values:
program Project14;
{$APPTYPE CONSOLE}
uses
SysUtils,
Xmldoc,
xmldom,
ActiveX;
var X: TXMLDocument;
Node: IDOMNode;
Sel: IDomNodeSelect;
begin
try
CoInitialize(nil);
X := TXMLDocument.Create(nil);
try
// Load XML from a string constant so I can include the exact XML sample from this
// question into the code. Note the "SomeNode" node, it's required to make that XML
// valid.
X.LoadFromXML(
'<SomeNode>'+
' <Link role="self">' +
' https://spatial.virtualearth.net/REST/v1/dataflows/Geocode/jobid' +
' </Link>' +
' <Status>Aborted</Status>' +
' <ErrorMessage>The data uploaded in this request was not valid.</ErrorMessage>' +
'</SomeNode>'
);
// Shortcut: Keep a reference to the IDomNodeSelect interface
Sel := X.DOMDocument as IDomNodeSelect;
// Extract and WriteLn() the values. Painfully simple!
WriteLn(Sel.selectNode('//Link[1]/node()').nodeValue);
WriteLn(Sel.selectNode('//Status[1]/node()').nodeValue);
WriteLn(Sel.selectNode('//ErrorMessage[1]/node()').nodeValue);
ReadLn;
finally X.Free;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
回答2:
If the XML-structure is fairly stable, you could use the XML binding tool to generate ordinary Delphi classes to access the xml-document.
Take a look at this page.
回答3:
Since there is an XML Schema for these Bing Spatial Data Services, the easiest way to go is to import that schema using the Delphi XML Data Binding Wizard, then use the generated Delphi classes and interfaces to get your data from the XML, or put data in the XML.
This is similar to what Jørn E. Angeltveit suggested, but his suggestion uses the plain XML to generate the classes from.
That is OK if you don't have a schema, but when you have a schema, it is always better to import the schema.
Thare are many examples on using the Delphi XML Data Binding Wizard, so start there first.
If you need help on the binding: please ask a new specific question here.
回答4:
Now you should parse XML file. In the most simple case (you know XML tags) it could look like this:
var
XMLDoc: IXMLDocument;
Node: IXMLNode;
I: Integer;
role, link: string;
begin
XMLDoc:= TXMLDocument.Create(nil);
XMLDoc.LoadFromFile(AFileName);
for I:= 0 to XMLDoc.DocumentElement.ChildNodes.Count - 1 do begin
Node:= XMLDoc.DocumentElement.ChildNodes[I];
if Node.NodeType = ntElement then begin
if Node.NodeName = 'Link' then begin
if Node.HasAttribute('role') then
role:= Node.Attributes['role'];
if not VarIsNull(Node.NodeValue) then
link:= Node.NodeValue;
[..]
end;
end;
end;
end;
来源:https://stackoverflow.com/questions/5483045/delphi-read-xml-element