I am new in Delphi, and here is the thing I want to do. I have XML file formated like this,
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Row>
<Designation>1234102</Designation>
<Inner>5.412</Inner>
<Outer>3.588</Outer>
<Spin>4.732</Spin>
<Cage>0.399</Cage>
</Row>
<Row>
<Designation>1342153</Designation>
<Inner>5.916</Inner>
<Outer>4.084</Outer>
<Spin>5.277</Spin>
<Cage>0.408</Cage>
</Row>
........
</Data>
and I want to query it with Delphi. For example: I want data of where is 1342153. What is the best and easiest solution?
Thank in advance for example and explanation.
I'm going to make the presumption that once you find the Designation
, you're going to want to also read the other entries (Inner
, Outer
, Spin
, and Cage
) that go with the designation.
XPath
is the perfect solution for this problem. My example uses a new form with just a TMemo
and TButton
dropped on it, and adding a handler for the Button1.OnClick
event:
uses
MSXML, ComObj, ActiveX;
const
XMLText = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
'<Data>' +
'<Row>' +
'<Designation>1234102</Designation>' +
'<Inner>5.412</Inner>' +
'<Outer>3.588</Outer>' +
'<Spin>4.732</Spin>' +
'<Cage>0.399</Cage>' +
'</Row>' +
'<Row>' +
'<Designation>1342153</Designation>' +
'<Inner>5.916</Inner>' +
'<Outer>4.084</Outer>' +
'<Spin>5.277</Spin>' +
'<Cage>0.408</Cage>' +
'</Row>' +
'</Data>';
procedure TForm1.Button1Click(Sender: TObject);
var
XMLDoc: IXMLDOMDocument;
Node, SibNode: IXMLDOMNode;
begin
Memo1.Clear;
XMLDoc := CoDOMDocument.Create;
XMLDoc.loadXML(XMLText);
// Select the node with the Designation you want.
Node := XMLDoc.selectSingleNode('//Designation[text()="1342153"]');
if Assigned(Node) then
begin
Memo1.Lines.Add('Found it.');
Memo1.Lines.Add(Node.nodeName + ' = ' + Node.firstChild.nodeValue);
// Read all the nodes at the same level as the Designation
SibNode := Node.nextSibling;
while SibNode <> nil do
begin
Memo1.Lines.Add(SibNode.nodeName + ' = ' +
SibNode.firstChild.nodeValue);
Sib := Sib.nextSibling;
end;
end;
end;
If you want to just grab all of the <Row>
elements, and loop through the information they contain, you can use this (add a second button to the test app above, and use this for the Button2.OnClick
handler):
procedure TForm1.Button2Click(Sender: TObject);
var
XMLDoc: IXMLDOMDocument;
NodeList: IXMLDOMNodeList;
Node, SibNode: IXMLDOMNode;
i: Integer;
begin
Memo1.Clear;
XMLDoc := CoDOMDocument.Create;
XMLDoc.loadXML(XMLText);
NodeList := XMLDoc.selectNodes('/Data/Row');
if Assigned(NodeList) then
begin
for i := 0 to NodeList.length - 1 do
begin
Node := NodeList.item[i];
SibNode := Node.firstChild;
while Assigned(SibNode) do
begin
Memo1.Lines.Add(SibNode.nodeName + ' = ' +
SibNode.firstChild.nodeValue);
SibNode := SibNode.nextSibling;
end;
end;
// Add a blank line between groupings for readability
Memo1.Lines.Add('');
end;
end;
As others suggested you can use XPath to find a particular value, in this case using this expression /Data/Row/Designation[text()="1342153"]
will locate the node which contains the value 1342153 in the Designation.
Try this sample code
{$APPTYPE CONSOLE}
{$R *.res}
uses
MSXML,
SysUtils,
ActiveX,
ComObj;
Const
XmlStr =
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'+
'<Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'+
' <Row>'+
' <Designation>1234102</Designation>'+
' <Inner>5.412</Inner>'+
' <Outer>3.588</Outer>'+
' <Spin>4.732</Spin>'+
' <Cage>0.399</Cage>'+
' </Row>'+
' <Row>'+
' <Designation>1342153</Designation>'+
' <Inner>5.916</Inner>'+
' <Outer>4.084</Outer>'+
' <Spin>5.277</Spin>'+
' <Cage>0.408</Cage>'+
' </Row>'+
'</Data>';
procedure Test;
Var
XMLDOMDocument : IXMLDOMDocument;
XMLDOMNode : IXMLDOMNode;
begin
XMLDOMDocument:=CoDOMDocument.Create;
XMLDOMDocument.loadXML(XmlStr);
XMLDOMNode := XMLDOMDocument.selectSingleNode('/Data/Row/Designation[text()="1342153"]');
if XMLDOMNode<>nil then
Writeln('Found');
end;
begin
try
CoInitialize(nil);
try
Test;
finally
CoUninitialize;
end;
except
on E:EOleException do
Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With