Transformacja XMLa

0

Mam problem z tranformacją xmla z następującej postaci:

<label align="inline">
        Blah
	<txt>
		<txt-a>
			<format param = 'nieok'/>
		</txt-a>
		<txt-b>Tekst </txt-b>
	</txt>

	<num>103
		<txt>
			<txt-a>
				<format trans = 'ok'/>
			</txt-a>
			<txt-b>5</txt-b>
		</txt>
		.
	</num>
</label>

na taką:

<label align="inline">
	Blah Tekst 103
	<txt>
		<txt-a>
			<format trans = 'ok'/>
		</txt-a>
		<txt-b>5</txt-b>
	</txt>
	.
</label>

Wszystkie txt, które mają txt-a/format [@param], muszą wylecieć. Num też musi wylecieć. Tekst tych node'ów ma jednak zostać.
Node'y txt, które mają txt-a/format[@trans] mają zostać.

Nie wiem kompletnie jak się za to wziąć. Nie mogę po prostu usunąć węzła, bo mi to go usuwa razem z zawartością. Nawet jeśli zachowam sobie zawartość jako string, nie mam pojęcia jak wstawić potem tego stringa w dokładnie to miejsce, z którego usunęłam node'a... Dodanie tekstu po prostu do InnerText doda go na koniec, czyli za kropkę.

Musiałabym więc pobrać najpierw pierwszą część tekstu (....jak?), dodać do tego InnerText pobrany z pierwszego txt, następnie dodać do tego OuterXml następnego txt i na koniec dorzucić resztę tekstu, czyli kropkę.
W powyższym jeszcze pominęłam porzucanie num, ale to po prostu jako krok wcześniej trzeba by wyciągnąć InnerXml z niego i dopiero wtedy dobierać się do reszty.

Czyli moje pytanie brzmi - jak wyciągnąć z XmlNode'a:

  • Blah
  • .

Dodam, że ten pierwszy txt to może, ale nie musi występować. Po txt a przed numem też może jeszcze się pojawić tekst. Jak sobie uświadamiam mnogość możliwych przypadków, to wydaje mi się, że i pytanie źle zadałam.

Czy jest jakiś sposób w C# na porzucenie określonych node'ów, ale zachowanie ich zawartości (w tym miejscu w którym był node)?

1

Mogłabyś trochę bardziej opisać co łączy się z czymś bo nie jestem pewien czy dobrze rozumiem co chcesz zrobić z tymi niczemu niewinnymi XML-ami?

Wygląda to tak (komentarze niezbyt xml-owe - przyzwyczajenie)

aurel napisał(a):
<label align="inline">
        Blah // luźne teksty na początku się łączą
	<txt>
		<txt-a>
			<format param = 'nieok'/> // pierwszy format wylatuje?
		</txt-a>
		<txt-b>Tekst </txt-b> // pierwszy txt-b wylatuje?
	</txt>

	<num>103 // to łączy się z Blah?
		<txt>
			<txt-a>
				<format trans = 'ok'/> // drugi format wylatuje?
			</txt-a>
			<txt-b>5</txt-b> // drugi txt-b zostaje?
		</txt>
		. // to zostaje?
	</num>
</label>
<label align="inline">
	Blah Tekst 103
	<txt>
		<txt-a>
			<format trans = 'ok'/>
		</txt-a>
		<txt-b>5</txt-b>
	</txt>
	.
</label>

PS. XDocument jest zazwyczaj wygodniejszy niż XmlDocument - masz narzucone z góry czy możesz wybierać?

0

To nie prościej użyć XSLT?

0

@msm, nie chcemy stracić żadnych danych, a jedynie niektóre znaczniki.
Wylecieć ma znacznik <num>, ale ma zostać jego zawartość.
Wylecieć ma cały zespół znaczników txt, które w txt-a/format mają atrybut "param", np.:

        <txt>
                <txt-a>
                        <format param = 'nieok'/> // wszystkie znaczniki w tym fragmencie wylatują, ponieważ mamy tu "param"
                </txt-a>
                <txt-b>Tekst </txt-b> //znaczniki wylatują, ale Tekst musi zostać
        </txt>

Drugi <txt> zostaje, ponieważ w txt-a/format ma "trans".

Nie mam narzucone XmlDocument, ale w linq też nie wiem jak to ugryźć (z linq miałam do tej pory do czynienia mało).

@somekind, może i prościej. Nie specjalnie lubię w tym pisać, ale jeżeli faktycznie nie ma w C# prostego sposobu na "porzucenie" znaczników, to nie będzie innego wyjścia...

0

Nie korzystałem z parserów xml w c#, ale innych DOM dlatego nie pokarzę implementacji.

Ja zrobił bym to tak wyszukał bym <format param="nieok" /> cofnął się do 2 parentów <txt>. Z tego wyszukał bym wszystkie węzły typu "TEXT" i je sobie osobno konkatenował po czym w siblings przed txt wstawił właśnie tego stringa i wywalił ten znacznik txt z zawartością.
Podejrzewam, że jako node type text będą też przerwy białych znaków uznawane więc po użyciu trim sprawdził bym czy został jakiś tekst jeśli tak dopiero konkatenował. podobnie z num'em.

0

Ok, próbuję iść drogą, którą wskazał @szopenfx.
Jak w C# wstawić przed danym node'm samą treść? Jest dostępna metoda InsertBefore, ale przyjmuje ona XmlNode, a nie potrafię zrobić XmlNode'a bez znacznika...

edit:
Dobra, leję na to, za dużo kombinowania. Zrobię to xslt.

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