Hallo Leute,
bekomme von einem Progamm viele automatisch erstellte xml-Dateien mit folgendem Inhalt:
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03 pain.001.001.03.xsd">
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>108-001-20150827143657034</MsgId>
<CreDtTm>2015-08-27T14:36:57.000Z</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>18972.43</CtrlSum>
<InitgPty>
<Nm>Firma</Nm>
</InitgPty>
</GrpHdr>
<PmtInf>
<PmtInfId>2015082714365703</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>5555.55</CtrlSum>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
</PmtTpInf>
<ReqdExctnDt>2015-10-15</ReqdExctnDt>
<Dbtr>
<Nm>Firma</Nm>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN>A55555555</IBAN>
</Id>
</DbtrAcct>
<DbtrAgt>
<FinInstnId>
<BIC>RREWEF3</BIC>
</FinInstnId>
</DbtrAgt>
<CdtTrfTxInf>
<PmtId>
<EndToEndId>1111111</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="EUR">5555.55</InstdAmt>
</Amt>
<CdtrAgt>
<FinInstnId>
<BIC>RRR23E</BIC>
</FinInstnId>
</CdtrAgt>
<Cdtr>
<Nm>HHHH</Nm>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN>5555555</IBAN>
</Id>
</CdtrAcct>
<Purp>
<Cd>OTHR</Cd>
</Purp>
<RmtInf>
<Strd>
<CdtrRefInf>
<Ref>55555</Ref>
</CdtrRefInf>
</Strd>
</RmtInf>
</CdtTrfTxInf>
</PmtInf>
</CstmrCdtTrfInitn>
</Document>
Benötige das CtrlSum.
Lese xml-Dateien eigentlich immer so aus:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(@"C:\Test\test2.xml");
XmlNode node = xmlDoc.SelectSingleNode("/Document/CstmrCdtTrfInitn/GrpHdr/CtrlSum");
string test = node.InnerText;
node ist aber immer NULL - was mache ich hier falsch?
DANKE!
Ich hab das XML mal normal formatiert. Wie soll denn einer helfen, wenn das XML absolut unlesbar ist und dazu noch die Darstellung beeinträchtigt? Bitte achte darauf. Mach es uns nicht so schwer dir zu helfen.
Der Beitrag wäre genau das Thema. Nur hat er niergendwo seine XML-Datei gepostet oder bin sehe ich jetzt schon den Wald vor lauter Bäumen nicht??
Du hast in der XML den Namespace urn:iso:std:iso:20022:tech:xsd:pain.001.001.03
machst diesen aber nirgends bekannt.
Dann findet er halt auch die Nodes nicht 😉
Ergo: XmlNamespaceManager verwenden.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
DANKE Leute... irgendwie schaffe ich es immer noch nicht:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(@"C:\Test\test2.xml");
XmlNamespaceManager nsMan = new XmlNamespaceManager(xmlDoc.NameTable);
nsMan.AddNamespace("", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03");
XmlNode test = xmlDoc.DocumentElement.SelectSingleNode("/CstmrCdtTrfInitn/GrpHdr/CtrlSum", nsMan);
Wie kommst Du auf die Idee, dass die Namespace Bezeichnung "" ist?
Nachgelesen, wie es funktioniert?
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hi Abt (danke für die Geduld).
Verstehe es leider nicht wirklich.
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03 pain.001.001.03.xsd">
Was genau ist jetzt der Namespace ( Da 2x xmlns) - das verstehe ich nicht ganz.
Habe es auch schon so probiert:
nsMan.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
Stand im Moment:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(@"C:\Users\Public\Documents\xml\TEST.xml");
XmlNamespaceManager nsMan = new XmlNamespaceManager(xmlDoc.NameTable);
nsMan.AddNamespace("ab", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03");
XmlNode node3 = xmlDoc.SelectSingleNode("/ab:CstmrCdtTrfInitn/GrpHdr/CtrlSum", nsMan);
Bin ich hier ganz falsch?
Also mit dem Namespace komme ich nicht zurecht... habe jetzt folgendes gefunden:
XmlNode hallo = xmlDoc.GetElementsByTagName("CtrlSum")[0];
String juhu = hallo.InnerText;
Funktionert auch:
XmlNode node3 = xmlDoc.SelectSingleNode("//ab:CtrlSum", nsMan);
Verstehe es Aber nicht - was ist mit den Knoten davor?
Bitte les Dich in XPath ein, dann verstehst Du den Unterschied von SelectNode("/.. und SelectNode("//.."
XML gehört zum Grundwissen von .NET, und XPath ist ein absolut erforderlicher Bestandteil davon.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
var xdoc = XDocument.Load(@"XMLFile1.xml");
var nspace = xdoc.Root.GetDefaultNamespace();
var checksum = Convert.ToDecimal(xdoc.Root.Descendants(nspace + "CtrlSum").First().Value, CultureInfo.InvariantCulture);
Aber mach dir dein Leben ruhig weiter schwer 😉
LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Habe ich hier gemacht:
XPath
Verstehe ich die schreibweise im C# hier nicht ganz dazu:
Laut dieser Erklärung hätte ich das so verstanden:
XmlNode node3 = xmlDoc.SelectSingleNode("//ab:GrpHdr/CtrlSum", nsMan);
oder so:
XmlNode node3 = xmlDoc.SelectSingleNode("/ab:CstmrCdtTrfInitn/GrpHdr/CtrlSum", nsMan);
CtrlSum kommt bei 2x vor deshalb.
Kann mir das jemand anhand eines Beispieles erklären das mehrere Unterknoten hat... weil mit einem funktioniert es..
Du verwendest SelectSingleNode - das ist Dir bewusst?
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Wenn du unbedingt mit XmlDocument und XPath hantieren willst - kann ich zwar an diesem Beispiel nicht nachvollziehen, aber okay - dann reicht Wikipedia nicht.
So ziemlich vollständige XPath-Erläuterung. Dazu solltest du dir mal die SelectNode-Methoden anschauen, du hebelst da an der falsch Stelle.
Oder du machst es halt in drei Zeilen inkl. Dokument öffnen mit XDocument.
LaTino
Nachtrag:
var xmldoc = new XmlDocument();
xmldoc.Load(@"XMLFile1.xml");
var nsMan = new XmlNamespaceManager(xmldoc.NameTable);
nsMan.AddNamespace("ns", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03");
var xmlNode = mldoc.SelectSingleNode("/ns:Document/ns:CstmrCdtTrfInitn/ns:GrpHdr/ns:CtrlSum", nsMan);
Zusatztipp: besorg dir ein ordentliches XML-Tool (wenn ich ISO 20022 lese, gehe ich eigentlich automatisch davon aus, dass Geld für eine LiquidXML-Lizenz vorhanden ist) und lass dir die XPath-Ausdrücke generieren. Bei so einfachen Sachen mag's gehen, aber wenn es etwas komplexer wird, verschwendet man wertvolle Hirnkapazitäten. (daher auch mein wiederholter Tipp mit Linq to xml)
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Hi Leute,
sorry ich war mit einer Grippe einige Tage außer Gefecht...
ZUERST mal danke für die Hilfe!!
@Abt... Ja, dachte SingleNode ist hier richtig, da ich ja wirklich nur einen Knoten eine auslesen möchte 🤔...
Habe diese Lösung auf der MSN-Seite gefunden bzw. auch immer wenn ich etwas zu XPath gelesen habe.
Was wäre hier der richtige Weg und warum?
@LTino
var xmlNode = mldoc.SelectSingleNode("/ns:Document/ns:CstmrCdtTrfInitn/ns:GrpHdr/ns:CtrlSum", nsMan);
Ok ich muss hier überall den NamesSpaceManager angeben....
Zusatztipp: besorg dir ein ordentliches XML-Tool (wenn ich ISO 20022 lese, gehe ich eigentlich automatisch davon aus, dass Geld für eine LiquidXML-Lizenz vorhanden ist) und lass dir die XPath-Ausdrücke generieren. Bei so einfachen Sachen mag's gehen, aber wenn es etwas komplexer wird, verschwendet man wertvolle Hirnkapazitäten. (daher auch mein wiederholter Tipp mit Linq to xml)
Das Programm das hier die XML-Dateien erstellt hat mit der IT nicht wirklich etwas zu tun. Dies wird von einer Abteilung im Haus verwendet ( wurde gekauft). Für die IT ist nie Geld übrig 😁
Mit Linq to xml habe ich mich noch nicht beschäftigt.
Dieses Beispiel funktiniert zwar aber ich verstehe es nicht ganz:
var xdoc = XDocument.Load(@"XMLFile1.xml");
var nspace = xdoc.Root.GetDefaultNamespace();
var checksum = Convert.ToDecimal(xdoc.Root.Descendants(nspace + "CtrlSum").First().Value, CultureInfo.InvariantCulture);
Müsste er hier nicht noch mehr finden? "CtrlSum" ist ja öfters vorhanden 🤔
Zusatz:
Bin noch nicht sehr lange in der Welt von C# (bin eher in Datenbanken unterwegs) - daher bin ich für eure Geduld sehr dankbar - DANKE.
Mir ist Bewusst das hier ist kein Anfängerforum - jedoch findet man sonst sehr wenige Foren die wirklich helfen bzw. auch Fachkenntnisse haben.
Hi,
du hast das .First() übersehen. Ja - er findet mehrere - gibt dir allerdings nur den ersten davon als decimal.
LG
Bitte beachte: [Hinweis] Wie poste ich richtig? Punkt 1.1. Gerade wenn man noch nicht so lange unterwegs ist.
Microsoft MVP // Me // Blog // GitHub // @Egghead // All my talks // Speakerdeck
sorry ich war mit einer Grippe einige Tage außer Gefecht...
Erstmal gute Besserung 😄
@Abt... Ja, dachte SingleNode ist hier richtig, da ich ja wirklich nur einen Knoten eine auslesen möchte 👶...
Viele Wege führen nach Rom. SelectSingleNode auch, wie du an meinem zweiten Beispiel siehst 😉.
var xmlNode = mldoc.SelectSingleNode("/ns:Document/ns:CstmrCdtTrfInitn/ns:GrpHdr/ns:CtrlSum", nsMan);
Ok ich muss hier überall den NamesSpaceManager angeben....
Nein. Der Namespacemanager ist nur ein Verzeichnis von "bekannten" Namespaces, für den Fall, dass ein XML-Dokument verschiedene benutzt. Im XPath musst du für jeden Knoten angeben, in welchem Namespace er definiert ist (das ist auch nötig, weil, wie gesagt jeder Knoten einen anderen ns haben könnte). Der NamespaceManager schaut dann nach, ob dieser ns ihm bekannt ist, und tut, was er tun muss beim Auswerten des XPath.
Das Programm das hier die XML-Dateien erstellt hat mit der IT nicht wirklich etwas zu tun. Dies wird von einer Abteilung im Haus verwendet ( wurde gekauft). Für die IT ist nie Geld übrig 😄
LiquidXML (zum Beispiel) ist nicht nur zum Erstellen von XML gut. Dokument laden, Rechtsklick auf irgendeinen Knoten -> XPath generieren. So oder ähnlich. Es ist zwar hilfreich, sich damit auszukennen, aber letzten Endes machen einen Tools produktiver.
Dieses Beispiel funktiniert zwar aber ich verstehe es nicht ganz:
var xdoc = XDocument.Load(@"XMLFile1.xml"); var nspace = xdoc.Root.GetDefaultNamespace(); var checksum = Convert.ToDecimal(xdoc.Root.Descendants(nspace + "CtrlSum").First().Value, CultureInfo.InvariantCulture);
Müsste er hier nicht noch mehr finden? "CtrlSum" ist ja öfters vorhanden 👶
Was Taipi88 schrieb. Im übrigen muss man bei solchen Ausdrücken - egal ob Linq2Xml oder XmlDocument - immer relativ genau wissen, was man tut. Da das in diesem speziellen XML verwendete Schema zwingend vorschreibt, dass
a) der CtrlSum-Knoten vorhanden sein MUSS
b) der von dir gewünschte Knoten im ersten Subknoten von Root zu finden sein MUSS
konnte man gefahrlos First() verwenden. In anderen XML-Dokumenten, insbesondere wenn die Reihenfolge oder Existenz nicht vorgeschrieben ist, mag so etwas vor den Baum gehen. Also, Obacht. Macht sich auch gut, Dokumente gegen ihr Schema zu validieren, bevor man sich drauf verlässt.
Edit: uh. https://wiki.xmldation.com/@api/deki/files/443/=ISO20022_Business_Rules_pain.001.001.03.png
Das Schema schreibt die CtrlSum NICHT zwingend vor. Also FirstOrDefault() und auf null prüfen.
LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Das mit dem .First war mir bewusst nur nicht im Zusammenhang mit dem Namespacemanager - habe hier etwas durcheinander gebracht.
ABER VIELEN DANK FÜR die HILFE - glaube es wurde hier alles Beantwortert!