![]() |
XML Knoten holen
Folgende XML (Auszug)
Code:
<AssetsList>
<Asset> <Template>Chain</Template> <Values> <Standard> <GUID>137596</GUID> <Name>chain 08</Name> </Standard> <ProductionChain> <Building>135669</Building> <Tier1> <Item> <Building>101415</Building> <Tier2> <Item> <Building>101272</Building> </Item> </Tier2> </Item> <Item> <Building>135224</Building> <Tier2> <Item> <Building>1010331</Building> </Item> <Item> <Building>134614</Building> <<<<<<<< </Item> <Item> <Building>135134</Building> <Tier3> <Item> <Building>101260</Building> </Item> <Item> <Building>101270</Building> </Item> </Tier3> </Item> </Tier2> </Item> </Tier1> </ProductionChain> </Values> </Asset> ........ </Assetlist> Hier suche ich jetzt zum Beispiel den Knoten <Building>134614</Building> oder besser den Wert. Kein Problem. Jetzt benötige ich aber den Wert des Knotens <GUID>. (Asset/Values/Standard/GUID) ParentNode geht da nicht, das Beispiel ist eines von Dutzenden mit unterschiedlicher Tiefe. Wie komme ich dahin? Da fehlt's bei mir. xreehawk |
AW: XML Knoten holen
Zitat:
* das eine <GUID> ist problemlos einfach * einer der, bzw. alle <Building> wird etwas schwerer Zum Thema ![]() Auch gibt es nette Programme und auch Online-Seiten, wo man gemütlich ausprobieren kann und sich teilweise auch Pfade generieren lassen kann. ![]() Vielleicht?
Delphi-Quellcode:
/Asset/Values/ProductionChain/Tier1/Item[2]/Tier2/Item[2]/Building
oder
Delphi-Quellcode:
/Asset/Values[Standard/GUID=137596]/ProductionChain/Tier1/Item[2]/Tier2/Item[2]/Building
oder
Delphi-Quellcode:
//ProductionChain[../Standard/GUID=137596]/Tier1/Item[2]/Tier2/Item[2]/Building
... |
AW: XML Knoten holen
Moin.
Also: der obige XML Auszug ist der Teile eine XML mit insgesamt 93 solcher Blöcke. Gegeben ist mir ein String : 134614 Diesen String suche ich in der gesamten XML. Er wird mit Sicherheit in einem dieser 93 Blöcke zu finden sein. Und von diesen Block benötige ich dann die <GUID>. Direkte Pfade kann ich vergessen, jeder der besagten Blöcke hat eine andere Tiefe, wie schon gesagt. creehawk |
AW: XML Knoten holen
Kannst du dich nicht von dem gefundenen Knoten über die ParentNodes hochhangeln bis <Asset> und von da aus Values/Standard/GUID auslesen?
|
AW: XML Knoten holen
Natürlich kann ich das.
Nur ist für fast jeden der Blöcke eine andere parentabfrage zu machen. Geht das nicht einfacher? creehawk |
AW: XML Knoten holen
So geht's..... als MischMasch aus XML und Strings.:oops:
Delphi-Quellcode:
Aber schön ist anders.:cry:
begin
ChainTexts := TStringlist.Create; ResultStrings := TStringlist.Create; ChainList := CoDOMDocument.create; ChainList.Load(ORGPath + 'ProductionChain.xml'); ChainRoot := ChainList.DocumentElement; ChainUnits := ChainRoot.childNodes; // 128 Einträge BuildingShortList := CoDOMDocument.create; BuildingShortList.Load(XMLPath + 'BuildingsShort.xml'); BuildingShortRoot := BuildingShortList.DocumentElement; BuildingShortNodes := BuildingShortRoot.childNodes; // 207 Einträge for I := 0 to BuildingShortNodes.Length-1 do begin GUID := BuildingShortNodes.item[I].attributes[0].text; for II := 0 to Chainunits.length-1 do begin ChainTexts := TStringlist.Create; ChainGUID := ChainUnits.item[II].SelectSingleNode('Values/Standard/GUID').text; ChainTexts.Add(ChainUnits.item[II].XML); for III:= 0 to ChainTexts.Count -1 do begin if AnsiPos(GUID, ChainTexts.Strings[III]) > 0 then ResultStrings.Add(ChainGUID + '#' + GUID) end; end; end; ResultStrings.SaveToFile(TMPPath + 'ChainGUIDs.txt'); end; creehawk |
AW: XML Knoten holen
Pos, AnsiPos oder sowas "unverständliches"
![]() ![]() ![]() ![]() Warum überhaupt Pos? Also warum ein Contains? Wenn du nach 12345 suchts und dann auch 01234567 findets. :freak: Wie in den Beispielen in #2 zu sehen, kann man im XPath auch Parameter, Parents, Childs, Siblings usw. prüfen. (darüber, darunter, daneben und sonstwo) Auch kann man absolut, relativ oder komplett frei suchen. |
AW: XML Knoten holen
Zitat:
Delphi-Quellcode:
Lösung ohne Gewähr. Die Funktion AnyTextFileToString beachtet das Format und konvertiert, wenn es notwendig ist. MakePath verkettet zu einem Pfad unter Berücksichtigung des OS. TExecutable ist eine Datenstruktur (Record) mit nützlichen Variablen zur sofortigen Verwendung.
function FindBuildingGUID(pmXMLStream: TStream; const pmcSearchBuilding: String): String; overload;
begin Result := ''; if pmXMLStream = Nil then Exit; //=> if pmcSearchBuilding = '' then Exit; //=> var xmlSize: Int64 := pmXMLStream.Size; if (xmlSize > 0) and (xmlSize < High(NativeInt)) then begin var parser: TParser := TParser.Create(pmXMLStream); try var runGUID: String; while parser.SourcePos < xmlSize do begin if parser.Token = '<' then begin parser.NextToken; if parser.Token = '/' then begin repeat parser.NextToken; until parser.Token = '>'; end else if parser.TokenSymbolIs('GUID') then begin parser.NextToken; // '>' closing tag parser.NextToken; // XML tag value runGUID := parser.TokenString; end else if parser.TokenSymbolIs('BUILDING') then begin parser.NextToken; // '>' closing tag parser.NextToken; // XML tag value if SameText(parser.TokenString, pmcSearchBuilding) then Exit(runGUID); //=> end; end; parser.NextToken; end; finally parser.Free; end; end; end; function FindBuildingGUID(const pmcXMLData, pmcSearchBuilding: String): String; overload; begin Result := ''; if pmcXMLData = '' then Exit; //=> if pmcSearchBuilding = '' then Exit; //=> var stream: TStringStream := TStringStream.Create(pmcXMLData); try Result := FindBuildingGUID(stream, pmcSearchBuilding); finally stream.Free; end; end; // Functions AnyTextFileToString, MakePath are from mORMot library. // Required Units: mormot.core.text, mormot.core.unicode, mormot.core.os begin var xml: String := AnyTextFileToString(MakePath([Executable.ProgramFilePath, 'daten.xml'])); ShowMessage(Format('GUID: %s', [FindBuildingGUID(xml, '134614')])); Bis bald... Thomas |
AW: XML Knoten holen
Nein, ich muss auf XML arbeiten.
Und AnsiPos muss jetzt nicht sein, ok, aber das war jetzt auch erstmal die Lösung die mir so einfiel..... Lass ich jetzt auch so, vielen Dank in jedem Fall für die Hinweise und Ideen, creehawk |
AW: XML Knoten holen
Wie gesagt, beim
Delphi-Quellcode:
if AnsiPos(GUID, ChainTexts.Strings[III]) > 0 then
aka
Delphi-Quellcode:
(ja, das wurde saublöd vom C# geklaukopiert und man muß auf die Parameter-Reihenfolge achten)
if ContainsStr(ChainTexts.Strings[III], GUID) then
dabei hätte ich eher das Gehühl, als wenn eigentlich Folgendes
Delphi-Quellcode:
if SameStr(GUID, ChainTexts.Strings[III]) then
aka
Delphi-Quellcode:
if GUID = ChainTexts.Strings[III] then
"gemeint" war. Und zusätzlich war's nur noch als Tipp, dass man Code auch "sprechend" schreiben kann, so dass er direkt sagt, was er eigentlich macht.
Delphi-Quellcode:
aka
a=b
Delphi-Quellcode:
(ja, prinzipiell sieht SameStr erstmal nutzlos aus, aber nicht, wenn man es in Bezug auf die anderen Funktionen betrachtet)
SameStr
Delphi-Quellcode:
aka
Pos()=0
Delphi-Quellcode:
oder
not ContainsStr()
Delphi-Quellcode:
not StartsStr()
Delphi-Quellcode:
aka
Pos()=1
Delphi-Quellcode:
StartsStr()
Delphi-Quellcode:
aka
Pos()<>0
Delphi-Quellcode:
ContainsStr()
Delphi-Quellcode:
aka
AnsiLowerCase(a)=AnsiLowerCase(b)
Delphi-Quellcode:
SameText
Delphi-Quellcode:
aka
Pos(AnsiLowerCase())=0
Delphi-Quellcode:
oder
not ContainsText()
Delphi-Quellcode:
not StartsText()
Delphi-Quellcode:
aka
Pos(AnsiLowerCase())=1
Delphi-Quellcode:
StartsText()
Delphi-Quellcode:
aka
Pos(AnsiLowerCase())<>0
Delphi-Quellcode:
ContainsText()
Links muß man auf leicht übersehbare Kleinigkeiten achten, aber Rechts steht es verständlich da. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:40 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz