Problem z selektywnym "czytaniem" danych z XML

0

Witam.
Nie mam doświadczeń z XML, a muszę pobrać dane z webservisu.
Otrzymuję plik o następującej strukturze"

<?xml version="1.0" encoding="ISO-8859-1"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
	<soap:Header/>
	<soap:Body>
		<ZdDocListGetResponse xmlns="http://www.serwer.pl">
			<ArrayZdDocListGetResult>
			<Status>1</Status>
			<ZdDocListGetResult>
				<ZdListGetHeaderResult>
					<DocId>222</DocId>
					<DocNo>2019/a/008</DocNo>
					<DateDoc>2019-01-10T00:00:00</DateDoc>
					<DocStatus>W</DocStatus>
					<DocAddressDelivery>Koluszki, ul Jasna 12 </DocAddressDelivery>
					<DocWarehouse>abc</DocWarehouse>
					<DateRealizationPlanned>2019-02-19T00:00:00</DateRealizationPlanned>
					<ArrayZdListGetLinesResult>
						<ZdListGetLinesResult>
							<PositionItem>1</PositionItem>
							<MaterialCode>23456</MaterialCode>
							<MaterialCatalogNumber>10-20-30</MaterialCatalogNumber>
							<MaterialDescription>Stolik nocny Prometeusz</MaterialDescription>
							<Quantity>2.0000</Quantity>
							<Unit>SZT</Unit>
						</ZdListGetLinesResult>
						<ZdListGetLinesResult>
							<PositionItem>2</PositionItem>
							<MaterialCode>386700</MaterialCode>
							<MaterialCatalogNumber>10-20-40</MaterialCatalogNumber>
							<MaterialDescription>Komoda Kasjopea</MaterialDescription>
							<Quantity>1.0000</Quantity>
							<Unit>SZT</Unit>
						</ZdListGetLinesResult>
					</ArrayZdListGetLinesResult>
					<ArrayZdListGetNotesResult/>
				</ZdListGetHeaderResult>
				<ZdListGetHeaderResult>
					<DocId>333</DocId>
					<DocNo>2019/b/009</DocNo>
					<DateDoc>2019-01-14T00:00:00</DateDoc>
					<DocStatus>W</DocStatus>
					<DocAddressDelivery>Pacanowo, kozia 2</DocAddressDelivery>
					<DocWarehouse>def</DocWarehouse>
					<DateRealizationPlanned>2019-02-27T00:00:00</DateRealizationPlanned>
					<ArrayZdListGetLinesResult>
						<ZdListGetLinesResult>
							<PositionItem>1</PositionItem>
							<MaterialCode>554433</MaterialCode>
							<MaterialCatalogNumber>10-20-30</MaterialCatalogNumber>
							<MaterialDescription>Stolik nocny Prometeusz </MaterialDescription>
							<Quantity>1.0000</Quantity>
							<Unit>SZT</Unit>
						</ZdListGetLinesResult>
						<ZdListGetLinesResult>
							<PositionItem>2</PositionItem>
							<MaterialCode>888999</MaterialCode>
							<MaterialCatalogNumber>10-20-50</MaterialCatalogNumber>
							<MaterialDescription>Szafa Viktoria </MaterialDescription>
							<Quantity>1.0000</Quantity>
							<Unit>SZT</Unit>
						</ZdListGetLinesResult>
					</ArrayZdListGetLinesResult>
					<ArrayZdListGetNotesResult/>
				</ZdListGetHeaderResult>
			</ZdDocListGetResult>
		</ArrayZdDocListGetResult>
	</ZdDocListGetResponse>
</soap:Body>
</soap:Envelope>

Bez problemu odczytuję sobie dane z poziomu <ZdListGetHeaderResult>:

XmlDocument doc = new XmlDocument();
doc.LoadXml(pobraneDane);
XmlNodeList DocId = doc.GetElementsByTagName("DocId");
XmlNodeList DocNoExternal = doc.GetElementsByTagName("DocNoExternal");
XmlNodeList DocNo = doc.GetElementsByTagName("DocNo");            
for (int i = 0; i < doc.Count; i++)
{
    dataGridView1.Rows.Add(DocId[i].InnerXml, DocNoExternal[i].InnerXml, DocNo[i].InnerXml);
}

Chciałbym jednak kolejny DGV wypełnić danymi szczegółowymi <ZdListGetLinesResult> dla <DocId>333</DocId>
Jak to zrobić? Szukałem po różnych forach, ale nigdzie nie znalazłem przykładu XML'a tak skomplikowanego.

0

Witam,

  1. Plik nie jest skomplikowany
  2. Zrób do tego serializację i wydłub sobie to co Ci potrzeba

Pozdrawiam,

mr-owl

0

Może tylko dla mnie skomplikowany - z prostymi radziłem sobie bez problemu.
Co do serializacji - mógłbyś podać przykład serializacji tego xml'a i wyciągnięcie wartości tagów <PositionItem>, <MaterialCode>, <MaterialCatalogNumber>, <MaterialDescription>, <Quantity>, <Unit> dla tagu <DocId> = 222

Z góry dziękuję.

0

Możesz zastosować 'klasyczne' podejście i wygenerować klasę mapującą Xml na obiekt:

  • jeśli korzystasz z Visual Studio to skopiuj z Xml'a tylko kawałek z danymi i wykorzystaj opcję w VS: Edit -> Paste Special -> Paste XML as Clasess
  • możesz także użyć zewnętrznego narzędzia jak xsd.exe lub Xsd2Code

Tutaj masz wygenerowaną klase: ZdDoc.cs

Następnie już w aplikacji możesz taki kawałek response zdeserializować, np. w taki sposób:

using (var ms = new System.IO.MemoryStream())
{
    ZdDocListGetResponse ZdDocList = (ZdDocListGetResponse)new XmlSerializer(typeof(ZdDocListGetResponse)).Deserialize(ms);
    var doc22 = ZdDocList.ArrayZdDocListGetResult.ZdDocListGetResult.Where(x => x.DocId == 22);
}

Zależnie czy czytasz to z dysku, z pamięci użyj odpowiedniego streamreadera.
BTW wygląda to na odpowiedź z web service - takie z czasów WCF, Soap więc nie wiem czy nie poszukał bym wsdl'a do tego i z niego korzystał.

0

Tak jak przypuszczałeś - jest to odpowiedź z web service - Soap.
Na tę chwilę tworzę z tego klasy z użyciem System.Xml.Linq.
Wklejania XML' jako klasy nie znałem, a widzę że bardzo ułatwia (przyspiesza) pracę.
Dzięki wielkie za wsparcie.

0

poczytaj o XPath i XmlDocument.CreateNavigator albo jak koledzy polecili XmlSerializer

1 użytkowników online, w tym zalogowanych: 0, gości: 1