Ich werd versuchen das Problem zu lösen, ggf. eine Funktion dafür schreiben und mich dann zu diesem Thema wieder melden.
Vielen Dank noch mal für Deine Hilfe.
XML und die Verwendung von XPath
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: XML und die Verwendung von XPath
Du kannst auch eine vorhandene optimieren:aXied hat geschrieben:Ich werd versuchen das Problem zu lösen, ggf. eine Funktion dafür schreiben und mich dann zu diesem Thema wieder melden.
Code: Alles auswählen
program Project1;
{$mode objfpc}{$H+}
uses
Classes, dom, XMLRead, XPath, sysutils
{ you can add units after this };
const
TESTDOC = '<?xml version="1.0" encoding="UTF-8"?>'
+'<root><c><abc id="1" /><abc id="2" /></c><b><abc id="3" /><abc id="4" /></b></root>';
// Zentrale Funkion, ermittelt den XML-Pfad
function GetNodePath(aNode: TDOMNode): DOMString;
// Position des Knotens in Bezug auf gleichnamige Geschwisterknoten
function GetPosition(aNode: TDOMNode): Integer;
var
nn: DOMString;
begin
nn := anode.NodeName;
Result := 0;
while assigned(aNode.PreviousSibling) do
begin
if aNode.NodeName = nn then
inc(Result);
aNode := aNode.PreviousSibling;
end;
end;
// Anzahl gleichnamiger Geschwisterknoten
function GetSameNameCount(aNode: TDOMNode): Integer;
var
nn: DOMString;
e: TDOMElement;
begin
Result := 0;
if aNode.NodeType = ELEMENT_NODE then
begin
nn := aNode.NodeName;
e := TDOMElement(aNode.ParentNode.FirstChild);
while assigned(e) do
begin
if e.NodeName = nn then
inc(result);
e := TDOMElement(e.NextSibling);
end;
Dec(result);
end;
end;
begin
if aNode.NodeType = ATTRIBUTE_NODE then
begin
Result := GetNodePath(TDOMAttr(aNode).OwnerElement) + '/';
Result := Result + '@' + aNode.NodeName;
end
else if aNode.NodeType = ELEMENT_NODE then
begin
if (aNode.ParentNode <> nil) then
begin
Result := GetNodePath(aNode.ParentNode) + '/';
end;
if (aNode.NodeType = DOCUMENT_NODE) OR (GetSameNameCount(aNode) = 0) then
Result := Result + aNode.NodeName
else
Result := Result + aNode.NodeName + Format('[%d]', [GetPosition(aNode)]);
end;
end;
var
doc: TXMLDocument;
searchednodes: TXPathVariable;
ss: TStringStream;
begin
ss := TStringStream.Create(TESTDOC);
ReadXMLFile(doc, ss);
ss.Destroy;
searchednodes := EvaluateXPathExpression('//*[@id="2"]/@id',doc);
writeln('Result Type Name: ', searchednodes.TypeName);
writeln('Path: ', GetNodePath(TDOMNode(searchednodes.AsNodeSet.Items[0])));
searchednodes.Release;
doc.Destroy;
readln;
end.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Re: XML und die Verwendung von XPath
Hallo socke.
Ich habe Deinen Code ausprobiert. Erste Tests mit einfachen XPath-Abfragen wurden erfolgreich aufgelöst.
Vielen Dank für Deine Hilfe.
Sollte ich tatsächlich noch optimieren können
, stelle ich den zugehörigen Code hier ein.
Ich habe Deinen Code ausprobiert. Erste Tests mit einfachen XPath-Abfragen wurden erfolgreich aufgelöst.

Vielen Dank für Deine Hilfe.
Sollte ich tatsächlich noch optimieren können

Re: XML und die Verwendung von XPath
Nachdem ich nun mit meiner Umstellung fast fertig bin, habe ich bei Tests noch einen kleinen Fehler in socke's Code entdeckt.
Diesen möchte ich wie versprochen korrigiert weitergeben.
Das Problem in der Funktion GetPosition ist/war, gibt es kein vorheriges Geschwister wurde als Position 0 zurück geliefert.
Falscher Code - Korrigierter Code
Diesen möchte ich wie versprochen korrigiert weitergeben.
Das Problem in der Funktion GetPosition ist/war, gibt es kein vorheriges Geschwister wurde als Position 0 zurück geliefert.
Falscher Code - Korrigierter Code
Code: Alles auswählen
// Position des Knotens in Bezug auf gleichnamige Geschwisterknoten
function GetPosition(aNode: TDOMNode): Integer;
var
nn: DOMString;
begin
nn := anode.NodeName;
[b][color=red]Result := 0;[/color][/b]
[b][color=green]Result := 1; //Die Zählung beginnt immer mit 1![/color][/b]
while assigned(aNode.PreviousSibling) do
begin
[b][color=green]aNode := aNode.PreviousSibling;[/color][/b]
if aNode.NodeName = nn then
inc(Result);
[b][color=red]aNode := aNode.PreviousSibling;[/color][/b]
end;
end;