Laden...

Wert von Knoten in XML-Datei auslesen

Erstellt von matte vor 8 Jahren Letzter Beitrag vor 8 Jahren 4.621 Views
M
matte Themenstarter:in
60 Beiträge seit 2014
vor 8 Jahren
Wert von Knoten in XML-Datei auslesen

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!

Hinweis von Coffeebean vor 8 Jahren

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.

J
251 Beiträge seit 2012
vor 8 Jahren

Mhh wohl nicht der Erste mit dem Problem: XML Knoten auslesen

M
matte Themenstarter:in
60 Beiträge seit 2014
vor 8 Jahren

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??

16.807 Beiträge seit 2008
vor 8 Jahren

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.

M
matte Themenstarter:in
60 Beiträge seit 2014
vor 8 Jahren

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);

16.807 Beiträge seit 2008
vor 8 Jahren

Wie kommst Du auf die Idee, dass die Namespace Bezeichnung "" ist?
Nachgelesen, wie es funktioniert?

M
matte Themenstarter:in
60 Beiträge seit 2014
vor 8 Jahren

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?

16.807 Beiträge seit 2008
vor 8 Jahren

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.

3.003 Beiträge seit 2006
vor 8 Jahren

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)

M
matte Themenstarter:in
60 Beiträge seit 2014
vor 8 Jahren

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..

16.807 Beiträge seit 2008
vor 8 Jahren

Du verwendest SelectSingleNode - das ist Dir bewusst?

3.003 Beiträge seit 2006
vor 8 Jahren

Wenn du unbedingt mit XmlDocument und XPath hantieren willst - kann ich zwar an diesem Beispiel nicht nachvollziehen, aber okay - dann reicht Wikipedia nicht.

XML/XSL/XPath/Einführung

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)

M
matte Themenstarter:in
60 Beiträge seit 2014
vor 8 Jahren

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.

1.029 Beiträge seit 2010
vor 8 Jahren

Hi,

du hast das .First() übersehen. Ja - er findet mehrere - gibt dir allerdings nur den ersten davon als decimal.

LG

2.207 Beiträge seit 2011
vor 8 Jahren

Bitte beachte: [Hinweis] Wie poste ich richtig? Punkt 1.1. Gerade wenn man noch nicht so lange unterwegs ist.

Enumerable.First-Methode

3.003 Beiträge seit 2006
vor 8 Jahren

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)

M
matte Themenstarter:in
60 Beiträge seit 2014
vor 8 Jahren

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!