Szukam czystego, eleganckiego i inteligentnego rozwiązania do usuwania przestrzeni nazw ze wszystkich elementów XML? Jak by to wyglądało?
Zdefiniowany interfejs:
public interface IXMLUtils
{
string RemoveAllNamespaces(string xmlDocument);
}
Przykładowy kod XML do usunięcia NS z:
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfInserts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<insert>
<offer xmlns="http://schema.peters.com/doc_353/1/Types">0174587</offer>
<type2 xmlns="http://schema.peters.com/doc_353/1/Types">014717</type2>
<supplier xmlns="http://schema.peters.com/doc_353/1/Types">019172</supplier>
<id_frame xmlns="http://schema.peters.com/doc_353/1/Types" />
<type3 xmlns="http://schema.peters.com/doc_353/1/Types">
<type2 />
<main>false</main>
</type3>
<status xmlns="http://schema.peters.com/doc_353/1/Types">Some state</status>
</insert>
</ArrayOfInserts>
Po wywołaniu RemoveAllNamespaces (xmlWithLotOfNs) powinniśmy otrzymać:
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfInserts>
<insert>
<offer >0174587</offer>
<type2 >014717</type2>
<supplier >019172</supplier>
<id_frame />
<type3 >
<type2 />
<main>false</main>
</type3>
<status >Some state</status>
</insert>
</ArrayOfInserts>
Preferowanym językiem rozwiązania jest C # na .NET 3.5 SP1.
Odpowiedzi:
Oto ostateczna odpowiedź. Użyłem świetnego pomysłu Jimmy'ego (który niestety nie jest kompletny) i pełnej funkcji rekursji, aby działać poprawnie.
Na podstawie interfejsu:
Przedstawiam tutaj ostateczne czyste i uniwersalne rozwiązanie C # do usuwania przestrzeni nazw XML:
Działa w 100%, ale nie testowałem go zbytnio, więc może nie obejmować niektórych specjalnych przypadków ... Ale to dobra podstawa na początek.
źródło
Oznaczona najbardziej użyteczna odpowiedź ma dwie wady:
Oto moje podejście do tego:
Przykładowy kod tutaj .
źródło
xmlns
również.(from a in e.Attributes().DistinctBy(x => x.Name.LocalName)
do przypadkulang=""ru-ru"" xml:lang=""ru-ru""
obowiązkowa odpowiedź za pomocą LINQ:
źródło
To wystarczy :-)
źródło
Podnieś to ponownie, w C # - dodana linia do kopiowania atrybutów:
źródło
Obowiązkowa odpowiedź przy użyciu XSLT:
źródło
I to jest idealne rozwiązanie, które usunie również elementy XSI. (Jeśli usuniesz xmlns i nie usuniesz XSI, .Net wrzeszczy na ciebie ...)
źródło
Regex.Replace(xmlStr, @"<(/?)([^>\s:]+):([^>]+)>", "<$1$3>")
Wiem, że to pytanie zostało rzekomo rozwiązane, ale nie byłem do końca zadowolony ze sposobu, w jaki zostało wdrożone. Znalazłem inne źródło tutaj na blogach MSDN, które ma nadpisaną
XmlTextWriter
klasę, która usuwa przestrzenie nazw. Trochę go poprawiłem, aby uzyskać inne rzeczy, które chciałem, takie jak ładne formatowanie i zachowanie elementu głównego. Oto, co mam w tej chwili w swoim projekcie.http://blogs.msdn.com/b/kaevans/archive/2004/08/02/206432.aspx
Klasa
Stosowanie
źródło
To rozwiązanie oparte na zaakceptowanej odpowiedzi Petera Stegnara.
Użyłem go, ale (jak zauważyli andygjp i John Saunders) jego kod ignoruje atrybuty .
Musiałem też zadbać o atrybuty, więc dostosowałem jego kod. Wersja Andy'ego to Visual Basic, to nadal jest C #.
Wiem, że minęło trochę czasu, ale być może pewnego dnia kogoś to uratuje.
źródło
Bardzo podobało mi się miejsce, w którym Dexter tam jedzie, więc przetłumaczyłem to na „płynną” metodę rozszerzenia:
Podejście „płynne” pozwala mi to zrobić:
źródło
Możesz to zrobić za pomocą Linq:
źródło
Nieznacznie zmodyfikowana odpowiedź Petera, działałaby dobrze również w przypadku atrybutu, w tym usunięcie przestrzeni nazw i prefiksu. Trochę przepraszam, że kod wygląda trochę brzydko.
źródło
Odpowiedzi Jimmy'ego i Petera były bardzo pomocne, ale w rzeczywistości usunęli wszystkie atrybuty, więc dokonałem niewielkiej modyfikacji:
źródło
Trochę za późno na imprezę na tym, ale oto, czego ostatnio użyłem:
(pobrane z tego wątku MSDN )
Edycja Zgodnie z poniższym komentarzem wydaje się, że chociaż usuwa to przedrostek przestrzeni nazw z węzłów, w rzeczywistości nie usuwa atrybutu xmlns. Aby to zrobić, musisz również zresetować nazwę każdego węzła do jego nazwy lokalnej (np. Nazwa bez przestrzeni nazw)
źródło
Aby atrybuty działały, pętla for do dodawania atrybutu powinna przejść po rekursji, należy również sprawdzić, czy IsNamespaceDeclaration:
źródło
Oto moja wersja Dexter Legaspi C # w VB.NET
źródło
Inne rozwiązanie uwzględniające ewentualne przeplatanie węzłów TEXT i ELEMENT, np .:
Kod:
źródło
Bez uciekania się do rozwiązania opartego na XSLT, jeśli chcesz mieć czyste, eleganckie i inteligentne, będziesz potrzebować wsparcia ze strony frameworka, w szczególności wzorca odwiedzających może sprawić, że będzie to proste. Niestety nie jest tutaj dostępny.
Zaimplementowałem to zainspirowane LINQ,
ExpressionVisitor
aby mieć podobną strukturę. Dzięki temu można zastosować wzorzec gościa do obiektów XML (LINQ-to-). (Przeprowadziłem ograniczone testy, ale działa dobrze, o ile mogę powiedzieć)ps, ta konkretna implementacja wykorzystuje niektóre funkcje .NET 4, aby implementacja była nieco łatwiejsza / czystsza (użycie
dynamic
i domyślne argumenty). Zapewnienie zgodności z .NET 3.5, a może nawet .NET 2.0 nie powinno być trudne.Następnie, aby zaimplementować gościa, oto uogólniony, który może zmienić wiele przestrzeni nazw (i użyty prefiks).
I mała pomocnicza metoda, aby piłka się toczyła:
Następnie, aby usunąć przestrzeń nazw, możesz to nazwać tak:
Korzystając z tego gościa, możesz napisać,
INamespaceMappingManager
aby usunąć wszystkie przestrzenie nazw.źródło
Proste rozwiązanie, które faktycznie zmienia nazwy elementów w miejscu, nie tworząc kopii, i całkiem nieźle zastępuje atrybuty.
Uwaga: nie zawsze zachowuje to oryginalną kolejność atrybutów, ale jestem pewien, że możesz to łatwo zmienić, jeśli jest to dla Ciebie ważne.
Zwróć też uwagę, że może to również spowodować wyjątek, jeśli masz atrybuty XElement, które są unikalne tylko w przestrzeni nazw, na przykład:
co naprawdę wydaje się nieodłącznym problemem. Ale ponieważ pytanie wskazywało na wyprowadzenie String, a nie XElement, w tym przypadku możesz mieć rozwiązanie, które wyprowadzi prawidłowy ciąg, który był nieprawidłowym XElement.
Podobała mi się również odpowiedź Joculla przy użyciu niestandardowego XmlWriter, ale kiedy jej spróbowałem, nie zadziałała. Chociaż wszystko wygląda na poprawne, nie mogłem stwierdzić, czy klasa XmlNoNamespaceWriter miała w ogóle jakiś wpływ; zdecydowanie nie usuwał przestrzeni nazw tak, jak chciałem.
źródło
Dodanie my to również czyści nazwy węzłów, które mają prefiksy przestrzeni nazw:
źródło
Wypróbowałem kilka pierwszych rozwiązań i nie zadziałały. Głównie problem z usuwaniem atrybutów, jak już wspomnieliśmy. Powiedziałbym, że moje podejście jest bardzo podobne do Jimmy'ego, używając konstruktorów XElement, które przyjmują obiekt jako parametry.
źródło
moja odpowiedź,
kod lite-most oparty na manipulacji ciągami znaków ,
źródło
Oto Regex Wymień jedną wkładkę:
Oto próbka: https://regex101.com/r/fopydN/6
Ostrzeżenie: mogą wystąpić przypadki skrajne!
źródło
Odpowiedź user892217 jest prawie poprawna. Nie skompiluje się tak, jak jest, dlatego wymaga niewielkiej korekty wywołania rekurencyjnego:
źródło
To zadziałało dla mnie.
źródło
Po długich poszukiwaniach rozwiązania tego właśnie problemu, ta strona wydawała się mieć najwięcej wołowiny ... jednak nic nie pasowało dokładnie, więc wybrałem staroświecki sposób i po prostu przeanalizowałem to, co chciałem. Mam nadzieję, że to komuś pomoże. (Uwaga: to również usuwa SOAP lub podobne elementy koperty.)
źródło
Bez odtwarzania całej hierarchii węzłów:
źródło
Wypróbowałem niektóre rozwiązania, ale jak twierdziło wielu, są pewne skrajne przypadki.
Użyłem niektórych z powyższych wyrażeń regularnych, ale doszedłem do wniosku, że jednoetapowe wyrażenie regularne jest niewykonalne.
Oto moje rozwiązanie, 2-krokowe wyrażenie regularne, znajdź tagi, usuń tagi, nie zmieniaj danych cdata:
Na razie działa na mnie w 100%.
źródło
Oto rozwiązanie tego problemu oparte na wyrażeniach regularnych ...
źródło
Myślę, że to jest najkrótsza odpowiedź (ale w przypadku konstrukcji takich jak, będziesz mieć inną dyskusję, mam również wyrażenie regularne do konwersji
"<bcm:info></bcm:info>"
na „<info></info>
”, ale nie zostało zoptymalizowane, jeśli ktoś mnie o to zapyta, udostępnię to. Więc moje rozwiązanie to:źródło