Wklej C++ po lewej i kliknij "Konwertuj" — zrobimy z tego XMLWklej kod C++

Co to narzędzie robi

W przeciwieństwie do C# czy Javy, C++ nie ma wbudowanego serializera XML. Jeśli potrzebujesz payloadu XML pasującego do structa albo klasy, to albo piszesz XML ręcznie, albo podpinasz pugixml, albo ściągasz Xerces-C++, albo budujesz to z Expatem — a każde z tych podejść to kupa klepania, zanim w ogóle uruchomisz test. Wklej tu swoje C++, a narzędzie wypluje XML za jednym zamachem, z każdym polem tam, gdzie trzeba.

Czyta kod tak, jak czyta go człowiek. struct Order { std::string orderId; std::vector<OrderItem> items; }; z designated initializerem z C++20 staje się <Order><orderId/><items><OrderItem/>...</items></Order>, z zagnieżdżonymi structami rozpakowanymi inline. Wartości std::string są prawidłowo escapowane (standardowe &, <, >, ", '), typy liczbowe zachowują formę literału, a bool wychodzi jako true / false, więc wynik parsuje się czysto względem dowolnego schematu, którego spodziewa się zgodny ze standardem czytnik XML.

Kontenery przyjmują kształt, jaki napisałbyś ręcznie. std::vector<T>, std::array i zwykłe tablice C zamieniają się w element-rodzica z jednym dzieckiem na każdy element, nazwanym po typie elementu. std::map i std::unordered_map wypluwają pary <Entry><Key/><Value/></Entry>. std::optional trzymający nullopt staje się pustym elementem, a nie znika — dzięki czemu schemat pozostaje spójny w round-tripie. Wklej wywołanie konstruktora, literał z designated initializerem albo same definicje typów; narzędzie ogarnia wszystkie trzy warianty.

Jak się tego używa

Trzy kroki. Działa, czy wklejasz pojedynczy struct, czy cały header plus przykładową instancję.

1

Wklej swoje C++ (albo spróbuj przykładu)

Wrzuć cokolwiek w C++ do lewego edytora — definicję structa, klasę z metodami, designated initializer albo wywołanie konstruktora. Możesz zostawić #include'y, komentarze i dyrektywy using; parser się nimi nie zmieli.

Wolisz czystego structa z przykładową instancją? Kliknij Załaduj przykład po realistyczny Order z zagnieżdżonymi OrderItem i Address, w składni designated initializera z C++20.

2

Naciśnij Konwertuj

Kliknij zielony przycisk Konwertuj. Narzędzie przechodzi po typach, rozwija zagnieżdżone structy i pisze XML. W trakcie pokazuje się krótki wskaźnik ładowania — zwykle trwa to poniżej jednej-dwóch sekund.

3

Skopiuj XML

Prawy panel wypełnia się poprawnie sformowanym, wciętym XML-em. Wklejasz go prosto do żądania SOAP, pliku konfiguracyjnego app.xml, fixture'a std::ifstream do testu jednostkowego albo testu pugixml load_string — jest poprawny, escapowany i gotowy do użycia.

Kiedy to naprawdę ratuje skórę

Prototypowanie payloadów SOAP / web service

Masz w C++ structa żądania do legacy endpointu SOAP i potrzebujesz realistycznego body XML, żeby wrzucić w SoapUI albo curla. Wklejasz structa, bierzesz XML, lecisz dalej.

Zasilanie fixture'ów testów pugixml / Xerces

Testy jednostkowe twojego loadera XML potrzebują różnorodnych poprawnych dokumentów. Pisanie ich ręcznie to nuda; generowanie z prawdziwych structów utrzymuje fixture'y w synchronizacji z typami, które testują.

Budowanie szablonów konfiguracji z kodu

Silnik gry, narzędzie CAD albo symulacja, która czyta ustawienia z XML, zwykle ma po stronie C++ structa Settings. Wklejasz go, dostajesz gotowy do edycji szablon XML na build release'owy — bez ręcznego klepania boilerplate'u.

Pomost do legacy'owych systemów XML

Stacki finansowe, zdrowotne i obronne dalej mówią po XML-owemu. Gdy nowy serwis C++ musi wypuścić XML-ową wiadomość do starego konsumenta, to narzędzie pokazuje, jak ma wyglądać kształt, zanim podepniesz prawdziwy serializer.

Częste pytania

Czy mogę wkleić cały plik headera z kilkoma structami?

Tak. Wklej cały header — każdy struct albo class przejdzie, zagnieżdżone typy są rozwijane inline, a odziedziczone publiczne składowe z klas bazowych są doklejane. Parser jest pobłażliwy wobec komentarzy, dyrektyw preprocesora i forward declaration.

Czy rozumie designated initializery z C++20?

Tak. Order order{ .orderId = "ORD-4821", .items = { ... } }; jest parsowane pole po polu, więc XML zachowuje nazwy, które wpisałeś. Stara, pozycyjna inicjalizacja agregatów (Order{ "ORD-4821", ... }) też działa, o ile definicja structa jest w tym samym wklejeniu — narzędzie może wtedy dopasować pozycje do nazw pól. Zobacz inicjalizację agregatów na cppreference.

Jak obsługuje std::vector, std::map i std::optional?

std::vector<T>, std::array i zwykłe tablice C stają się elementem-kontenerem z jednym dzieckiem na każdy element, nazwanym po typie elementu. std::map / std::unordered_map wypluwają pary <Entry><Key/><Value/></Entry>. std::optional z nullopt staje się pustym elementem zamiast zostać pominięty, więc element pozostaje obecny w schemacie.

Po co więc nie użyć po prostu pugixml albo libxml2?

Świetnie nadają się do serializacji w runtime, ale napisanie pierwszego fixture'a — albo szablonu konfigu, albo przykładu do dokumentacji — i tak oznacza wyklepanie drzewa XML ręcznie. To narzędzie oszczędza tobie tę pierwszą rundę klepania. Wynik później zawsze możesz przepuścić przez pugixml, Xerces-C++ albo RapidXML.

Czy mój kod jest zapisywany?

Kod trafia na backend do konwersji i nie jest utrwalany — nie logujemy payloadów. Jeśli kod jest naprawdę wrażliwy (wewnętrzności zamkniętego silnika gry, modele tradingowe itp.), rzuć na niego okiem przed wklejeniem, jak przy każdym narzędziu online.

A co, jeśli C++ ma templaty, wskaźniki albo smart pointery?

Konkretne instancje templatów typu std::vector<int> działają od ręki. Nierozwiązane parametry szablonu (template<typename T> bez konkretnego T) lądują jako puste elementy — wybierz konkretny typ, jeśli chcesz prawdziwych danych. Zwykłe wskaźniki oraz std::unique_ptr/std::shared_ptr są prześledzane do obiektu, na który wskazują; wskaźnik nullowy staje się pustym elementem, zamiast wywalać całą konwersję.

Inne narzędzia, które mogą się przydać

C++ na XML to tylko jeden kawałek układanki. Te narzędzia dobrze z nim grają: