AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

XML Knoten holen

Ein Thema von creehawk · begonnen am 2. Aug 2023 · letzter Beitrag vom 3. Aug 2023
Antwort Antwort
creehawk

Registriert seit: 1. Jul 2013
Ort: Hamburg
241 Beiträge
 
Delphi 10.4 Sydney
 
#1

XML Knoten holen

  Alt 2. Aug 2023, 19:48
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

Geändert von creehawk ( 3. Aug 2023 um 06:40 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#2

AW: XML Knoten holen

  Alt 2. Aug 2023, 20:32
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) ...
Meinst du das nicht andersrum?
* das eine <GUID> ist problemlos einfach
* einer der, bzw. alle <Building> wird etwas schwerer

Zum Thema Bei Google suchenXPath finden sich genügend Erklärungen und Hilfen.
Auch gibt es nette Programme und auch Online-Seiten, wo man gemütlich ausprobieren kann und sich teilweise auch Pfade generieren lassen kann.
Bei Google suchenXPath online

Vielleicht?
/Asset/Values/ProductionChain/Tier1/Item[2]/Tier2/Item[2]/Building
oder
/Asset/Values[Standard/GUID=137596]/ProductionChain/Tier1/Item[2]/Tier2/Item[2]/Building
oder
//ProductionChain[../Standard/GUID=137596]/Tier1/Item[2]/Tier2/Item[2]/Building
...
$2B or not $2B

Geändert von himitsu ( 2. Aug 2023 um 21:15 Uhr)
  Mit Zitat antworten Zitat
creehawk

Registriert seit: 1. Jul 2013
Ort: Hamburg
241 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: XML Knoten holen

  Alt 3. Aug 2023, 06:45
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

Geändert von creehawk ( 3. Aug 2023 um 06:53 Uhr)
  Mit Zitat antworten Zitat
bcvs

Registriert seit: 16. Jun 2011
703 Beiträge
 
Delphi 12 Athens
 
#4

AW: XML Knoten holen

  Alt 3. Aug 2023, 08:12
Kannst du dich nicht von dem gefundenen Knoten über die ParentNodes hochhangeln bis <Asset> und von da aus Values/Standard/GUID auslesen?
  Mit Zitat antworten Zitat
creehawk

Registriert seit: 1. Jul 2013
Ort: Hamburg
241 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: XML Knoten holen

  Alt 3. Aug 2023, 09:12
Natürlich kann ich das.

Nur ist für fast jeden der Blöcke eine andere parentabfrage zu machen.

Geht das nicht einfacher?

creehawk
  Mit Zitat antworten Zitat
creehawk

Registriert seit: 1. Jul 2013
Ort: Hamburg
241 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: XML Knoten holen

  Alt 3. Aug 2023, 11:34
So geht's..... als MischMasch aus XML und Strings.

Delphi-Quellcode:
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;
Aber schön ist anders.

creehawk
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#7

AW: XML Knoten holen

  Alt 3. Aug 2023, 12:57
Pos, AnsiPos oder sowas "unverständliches"

Delphi-Referenz durchsuchenSameStr (OK, das ist ein =), Delphi-Referenz durchsuchenSameText, Delphi-Referenz durchsuchenStartsStr, StartsText, Delphi-Referenz durchsuchenContainsStr, ContainsText uvm.

Warum überhaupt Pos?
Also warum ein Contains?
Wenn du nach 12345 suchts und dann auch 01234567 findets.


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.
$2B or not $2B
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
472 Beiträge
 
#8

AW: XML Knoten holen

  Alt 3. Aug 2023, 16:44
So geht's..... als MischMasch aus XML und Strings.
Hast du die Wahl des Datenformats? JSON lässt sich einfacher verarbeiten. Wenn die Struktur nicht kompliziert ist, dann kannst du das XML auch einfach parsen:
Delphi-Quellcode:
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')]));
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.

Bis bald...
Thomas

Geändert von mytbo ( 4. Aug 2023 um 15:06 Uhr) Grund: Beschreibung der mORMot Funktionen hinzugefügt
  Mit Zitat antworten Zitat
creehawk

Registriert seit: 1. Jul 2013
Ort: Hamburg
241 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: XML Knoten holen

  Alt 3. Aug 2023, 17:00
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
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

AW: XML Knoten holen

  Alt 3. Aug 2023, 17:24
Wie gesagt, beim
if AnsiPos(GUID, ChainTexts.Strings[III]) > 0 then
aka
if ContainsStr(ChainTexts.Strings[III], GUID) then (ja, das wurde saublöd vom C# geklaukopiert und man muß auf die Parameter-Reihenfolge achten)

dabei hätte ich eher das Gehühl, als wenn eigentlich Folgendes
if SameStr(GUID, ChainTexts.Strings[III]) then
aka
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.
a=b aka SameStr (ja, prinzipiell sieht SameStr erstmal nutzlos aus, aber nicht, wenn man es in Bezug auf die anderen Funktionen betrachtet)
Pos()=0 aka not ContainsStr() oder not StartsStr()
Pos()=1 aka StartsStr()
Pos()<>0 aka ContainsStr()

AnsiLowerCase(a)=AnsiLowerCase(b) aka SameText
Pos(AnsiLowerCase())=0 aka not ContainsText() oder not StartsText()
Pos(AnsiLowerCase())=1 aka StartsText()
Pos(AnsiLowerCase())<>0 aka ContainsText()

Links muß man auf leicht übersehbare Kleinigkeiten achten, aber Rechts steht es verständlich da.
$2B or not $2B

Geändert von himitsu ( 3. Aug 2023 um 17:31 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:16 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz