pimp1310
Goto Top

Powershell Skript: XML-Dateien durchsuchen und vergleichen

Hallo Miteinander,

ich bin noch Anfänger was das Schreiben von Skripten für die Windows Powershell angeht, ich würde gerne mein Problem bzw. was ich vorhabe kurz erläutern.

Ich habe einen Ordner "Eingabe" in dem sich mehrere .xml Dateien mit folgender Struktur befinden

<line_items>
<line_item>
<line_item_number>1</line_item_number>
<customers_article_number>7321351321445330</customers_article_number>
<quantity_ordered>0</quantity_ordered>
<quantity_unit_ordered>PCE</quantity_unit_ordered>
<quantity_last_delivered>500</quantity_last_delivered>
<quantity_unit_last_delivered>PCE</quantity_unit_last_delivered>
<quantity_receipts_cumulated>131040</quantity_receipts_cumulated>
<quantity_unit_receipts_cumulated>PCE</quantity_unit_receipts_cumulated>
<quantity_receipts_cumulated_date_start>2000-01-01</quantity_receipts_cumulated_date_start>
<item_description>XXXXX</item_description>
<delivery_date_type>F</delivery_date_type>
<delivery_date>2025-02-24</delivery_date>
<schedule_state>1</schedule_state>
<frequency>2</frequency>
<place_of_discharge>WE</place_of_discharge>

Ich möchte nun die Nummer im Feld "customers_article_number" vorgeben und es soll dann alle XML-Dateien durchsuchen und vergleichen und mir die entsprechenden Felder quantity_receipts_cumulated und quantity_last_delivered ausgeben.

Ich hoffe, dass das möglich ist, ich würde die Ausgangsnummer in "customers_article_number" von Hand in die Datei eintragen, oder gibt es eine nette Möglichkeit?

Das habe ich schon, aber ich weiß nicht, ob das richtig ist oder ob das der falsche Ansatz ist, so wie ich das verstehe, da würde er ja nur die 3 Felder nehmen, oder?

$files = Get-ChildItem -Path c:\test_robin\eingabe\ -Filter *.xml
$files | Foreach-Object {
    $doc = [XML] (Get-Content -Path $_.FullName)
    $lPos = $doc.selectNodes("//customers_article_number")    
    $2Pos = $doc.selectNodes("//quantity_receipts_cumulated")    
    $lPos | select quantity_last_delivered
    $2Pos | select quantity_receipts_cumulated
}

Vielen Dank

Content-ID: 669960

Url: https://administrator.de/contentid/669960

Ausgedruckt am: 04.12.2024 um 19:12 Uhr

Michi91
Michi91 04.12.2024 aktualisiert um 09:55:51 Uhr
Goto Top
Ich habe ChatGPT befragt, der Code sieht erstmal pausibel aus.

Deine XML scheint allerdings nicht vollständig zu sein, es fehlen Closings z.B. für line_item.
Wenn deine XML weitere Verschachtelungen hat, wir der nachfolgende Code vermutlich nicht auf Anhieb funktionieren.

KI generierter Code, leicht angepasst durch mich:

# Definiere die Artikelnummer, nach der gesucht werden soll

# Artikelnummer, die gesucht werden soll
$targetArticleNumber = Read-Host "Bitte die Artikelnummer eingeben (customers_article_number)"  


# Pfad zum Ordner mit den XML-Dateien
$inputFolder = "C:\Pfad\zu\eingabe"  

# Alle XML-Dateien im Ordner einlesen
$xmlFiles = Get-ChildItem -Path $inputFolder -Filter *.xml

# Ergebnisspeicher initialisieren
$results = @()

foreach ($file in $xmlFiles) {
    # XML-Datei laden
    try {
        $xml = [xml](Get-Content -Path $file.FullName)
    } catch {
        Write-Warning "Konnte Datei $($file.FullName) nicht einlesen."  
        continue
    }

    # Durchsuche <line_item> Elemente
    foreach ($item in $xml.line_items.line_item) {
        if ($item.customers_article_number -eq $targetArticleNumber) {
            # Felder extrahieren
            $result = [PSCustomObject]@{
                FileName                     = $file.Name
                CustomersArticleNumber       = $item.customers_article_number
                QuantityReceiptsCumulated    = $item.quantity_receipts_cumulated
                QuantityLastDelivered        = $item.quantity_last_delivered
            }
            $results += $result
        }
    }
}

# Ergebnisse ausgeben
if ($results.Count -gt 0) {
    Write-Host "Gefundene Einträge:" -ForegroundColor Green  
    $results | Format-Table -AutoSize
} else {
    Write-Host "Keine passenden Einträge gefunden." -ForegroundColor Yellow  
}

# Optional: Ergebnisse in eine CSV-Datei exportieren
$results | Export-Csv -Path "$inputFolder\Ergebnisse.csv" -NoTypeInformation -Encoding UTF8  
Oskar44
Oskar44 04.12.2024 aktualisiert um 10:04:16 Uhr
Goto Top
$customers_article_number = Read-Host "Nummer eingeben"  
$folder = "D:\Ordner"  
foreach($file in Get-Childitem -LiteralPath $folder -File -Filter *.xml | ?{Select-XML -Path $_.Fullname -XPath "//customers_article_number[.='$customers_article_number']"}){  
    $xml = New-Object XML
    $xml.Load($file.Fullname)
    $xml.SelectNodes("//line_item[customers_article_number = '$customers_article_number']") | select @{n='Path';e={$file.Fullname}},quantity_last_delivered,quantity_receipts_cumulated  
}
pimp1310
pimp1310 04.12.2024 um 10:08:10 Uhr
Goto Top
Hi.


danke ja genau das war nur ein Ausschnitt, was benötigst du denn noch? ich kann leider die ganze xml nicht anfügen wegen Datenschutz.

es gibt davor noch ein

transmission
documents
document
Oskar44
Oskar44 04.12.2024 aktualisiert um 10:23:10 Uhr
Goto Top
Oder noch schlanker
$customers_article_number = Read-Host "Nummer eingeben"  
$folder = "D:\Daten"  
Select-XML -Path "$folder\*.xml" -XPath "//line_item[customers_article_number='$customers_article_number']" | select Path,@{n='quantity_last_delivered';e={$_.node.quantity_last_delivered}},@{n='quantity_receipts_cumulated';e={$_.node.quantity_receipts_cumulated}}  

Beide Codes erfolgreich mit Beispieldateien getestet. Ne KI braucht es für sowas simples nicht.
pimp1310
pimp1310 04.12.2024 um 10:24:36 Uhr
Goto Top
ahh ich muss leider nochmal korrigieren, es gibt den block "<line_items><line_item>" und das Feld "customers_article_number" mehrmals und auch diese nummer kann in einem xml Dokument mehrfach vorkommen.
Oskar44
Oskar44 04.12.2024 aktualisiert um 10:27:29 Uhr
Goto Top
Zitat von @pimp1310:

ahh ich muss leider nochmal korrigieren, es gibt den block "<line_items><line_item>" und das Feld "customers_article_number" mehrmals und auch diese nummer kann in einem xml Dokument mehrfach vorkommen.

Berücksichtigen beide meiner Codes bereits.
pimp1310
pimp1310 04.12.2024 um 10:34:50 Uhr
Goto Top
Hi

deine Codes liefern mir leider kein Ergebnis.
Da passiert einfach nix.


hatte deinen Code angepasst nach meinem verständnis das er mir anzeigen soll wenn keine ergebnisse und das er es mir exportiert

$customers_article_number = Read-Host "Bitte die Artikelnummer eingeben (customers_article_number)"   

# Ergebnisspeicher initialisieren
$results = @()

# Ordner Definition
$folder = "c:\test_robin\eingabe"    
$outputfolder = "c:\test_robin\ausgabe"   

# Funktion 
Select-XML -Path "$folder\*.xml" -XPath "//line_item[customers_article_number='$customers_article_number']" | select Path,@{n='quantity_last_delivered';e={$_.node.quantity_last_delivered}},@{n='quantity_receipts_cumulated';e={$_.node.quantity_receipts_cumulated}}    

# Ergebnisse ausgeben
if ($results.Count -gt 0) {
    Write-Host "Gefundene Eintraege:" -ForegroundColor Green    
    $results | Format-Table -AutoSize
} else {
    Write-Host "Keine passenden Eintraege gefunden." -ForegroundColor Yellow    
}

# Optional: Ergebnisse in eine CSV-Datei exportieren
$results | Export-Csv -Path "$outputfolder\Ergebnisse.csv" -NoTypeInformation -Encoding UTF8   
Oskar44
Oskar44 04.12.2024 aktualisiert um 10:42:08 Uhr
Goto Top
deine Codes liefern mir leider kein Ergebnis.
Da passiert einfach nix.
Wenn deine XML-Dateien Namespaces verwenden musst du uns das auch sagen die muss man nämlich zwingend mit angeben wenn man XPath benutz, klappt hier nämlich einwandfrei!!
Deswegen braucht man bei sowas am besten immer die ganze Datei von beginn an mit allen verwendeten Namespaces!

hatte deinen Code angepasst nach meinem verständnis das er mir anzeigen soll wenn keine ergebnisse und das er es mir exportiert
Ist falsch angepasst.

Wenn mit Export dann so

$customers_article_number = Read-Host "Nummer eingeben"    
$folder = "D:\Daten"    
$export = "D:\results.csv"    
$results = Select-XML -Path "$folder\*.xml" -XPath "//line_item[customers_article_number='$customers_article_number']" | select Path,@{n='quantity_last_delivered';e={$_.node.quantity_last_delivered}},@{n='quantity_receipts_cumulated';e={$_.node.quantity_receipts_cumulated}}    
if ($results){
    $results | export-csv -Path $export -Delimiter ";" -NoType -Encoding UTF8  
     write-host "Einträge gefunden und exportiert ..."  
}else{
    write-warning "Nichts gefunden"  
}
pimp1310
pimp1310 04.12.2024 um 10:39:46 Uhr
Goto Top
ich war so stolz auf mich face-sad


was brauchst du denn noch von mir ?
Oskar44
Oskar44 04.12.2024 aktualisiert um 10:42:24 Uhr
Goto Top
Zitat von @pimp1310:
was brauchst du denn noch von mir ?
Habe ich oben geschrieben. Eine XML Datei von Anfang an inklusive Namespace Statements.
pimp1310
pimp1310 04.12.2024 um 10:44:21 Uhr
Goto Top
okay, ja sagte ja bereits ist schweierig wegen datenschutz, ich würde die eben bearbeiten und poste sie dann gleich hier.

vielen Dank
pimp1310
pimp1310 04.12.2024 aktualisiert um 11:11:58 Uhr
Goto Top
Oskar44
Oskar44 04.12.2024 aktualisiert um 11:11:11 Uhr
Goto Top
Alles klar, wie vermutet ein Namespace im Einsatz, hiermit klappt es dann :
Bitte die Pfade anpassen und den Namespace http://www.XXX.de/UNIDOC im Skript deanonymisieren wenn du es bei dir verwenden willst
$customers_article_number = Read-Host "Nummer eingeben"      
$folder = "D:\Daten"      
$export = "D:\results.csv"  
$results = Select-XML -Path "$folder\*.xml" -XPath "//ns:line_item[ns:customers_article_number='$customers_article_number']" -Namespace @{ns="http://www.XXX.de/UNIDOC"} | select Path,@{n='quantity_last_delivered';e={$_.node.quantity_last_delivered}},@{n='quantity_receipts_cumulated';e={$_.node.quantity_receipts_cumulated}}  
if ($results){
    write-host "Einträge gefunden und exportiert:"        
    $results | format-table -AutoSize
    $results | export-csv -Path $export -Delimiter ";" -NoType -Encoding UTF8 -Force  
}else{
    write-warning "Nichts mit der Nummer '$customers_article_number' gefunden!"    
}
Oskar44
Oskar44 04.12.2024 aktualisiert um 11:27:42 Uhr
Goto Top
Falls du aus jeder Datei nur ein einziges eindeutiges Ergebnis für den Artikel haben willst wenn es mehrere mit der selben Nummer gibt, dann hängst du in Zeile 4 zusätzlich noch folgendes hinten an
 | select * -Unique
Je nachdem wie du es halt brauchst, wissen wir hier ja nicht.