Powszechność dziwnych praktyk w XML

4

Przykład ilustrujący to, o czym chcę pisać.

Kod produkcyjny w XML:

<key>impossible_difficulty_enabled</key>
<true/>

(pochodzi on z plików pewnej gry kupionej przeze mnie na Steamie)

Jak widzę tego rodzaju kod w XMLu to zaczynam zgrzytać zębami.

Ale kiedy to przeczytałem, zauważyłem u siebie, że nie czuję już zdziwienia, kiedy to czytam. To, że XMLe tak wyglądają, traktuję już jako normę. Czuję raczej irytację, choć w zasadzie nie powinienem, bo to przecież nie mój kod i ja z nim pracować nie muszę.

Na podstawie mojego niezbyt wielkiego doświadczenia wydaje mi się, że kod w XMLu w ten sposób wygląda bardzo często.

Ale to właśnie w XMLu. W na przykład JSONie już raczej by się czegoś takiego nie spotkało. Nikt nie napisałby chyba czegoś takiego:

{
    "key": "impossible_difficulty_enabled",
    "true": {}
}

Analogiczny zapis w JSONie wyglądałby raczej tak:

{
    "impossible_difficulty_enabled": true
}

Czy XML jest jakiś upośledzony?

Mimo wszystkich dziwactw XMLa da się w nim przecież pisać nawet prościej, niż w JSONie:

<impossible_difficulty_enabled/>

ALbo chociaż:

<impossible_difficulty_enabled>
    <true/>
</impossible_difficulty_enabled>

XML jest mocno przekombinowany, to fakt. Ale przekombinowanie samego XMLa to jedno, natomiast praktyki przekombinowujące kod w XMLu to drugie. Jeśli już ktoś pisze w XMLu, to czemu nie będzie chociaż tego pisał tak, żeby to miało ręce i nogi? Czemu do dziwactw XMLa musi dodawać jeszcze dziwactwa własne?

  1. Czy mam rację, czy mi się tylko niesłusznie wydaje, że XMLe bardzo często wyglądają w ten sposób, jaki podałem w przykładzie na początku mojego posta?
  2. Jeśli tak, to z czego to wynika? Może jest jakiś istotny powód, dla którego ludzie tak piszą XMLe, tyle że ja go nie znam?
0

a dlaczemu nie

<impossible_difficulty_enabled=true/>

albo

<key>impossible_difficulty_enabled</key>
<value>true</value>

żeby to jakoś sensownie wyglądało

btw z taką postacią, jak podałeś jeszcze się nie spotkałem

3

Dobrze, ale po co w ogóle zaglądasz do jakichś losowych xmli na świecie? :P

Może jakaś nowoczesna biblioteka do serializacji tak serializuje, kto wie.

3

Jako zagorzały przeciwnik XMLa nigdy nie myślałem o tym problemie. IMO to wynika z tego, że XML nie mapuje się na nic, co jest reprezentowane jako struktury danych w językach programowania. JSON jest trywialny do serializacji/parsowania (poza liczbami, ale to dużo mniejszy problem) w dowolnym języku programowania. Z drugiej strony mamy XMLa w którym możemy przedstawić to samo za pomocą różnych konceptów. Mamy node vs attribute, <key>value</key> vs <node><key>key</key><value>value</value></node> nie wiemy jak przedstawiać kolekcję, nie wiemy, czy subnody w danym nodzie to klucze w mapie/strukturze czy cholera wie co.

Pewnie to wygląda tak, że ktoś coś kiedyś pokracznie przedstawi, bo nie ma jasnej wykładni/oczywistego sposobu jak rozwiązać dany problem. Po tym przychodzi ktoś inny i zaczyna kopiować to co zobaczył i tak się tworzą różne dialekty. Np. ja pracowałem w takim projekcie, gdzie wszystko było przedstawiane jako atrybuty. Nody nie zawierały wartości innych, niż inne nody. Co niestety rodziło takie patologie jak ad-hoc struktury danych jak np attrValue="comma,separated,list"

4

XML to po prostu nie jest i nie był język/format stworzony do przechowywania, wysyłania danych i konfiguracji.

To jest po prostu markup langauge, czyli język do oznacza elementów w tekście, tak samo z resztą jak np html i markdown.

Stosowało się w nim konfigurację powiedziałbym z braku laku, ale teraz mamy alternatywy, np yaml. JSON moim skromnym zdaniem to też średni kandydat na trzymanie konfiguracji.

3

Czemu do dziwactw XMLa musi dodawać jeszcze dziwactwa własne?

Zapewne z tego samego powodu, dla którego w 2020+ wybrano XML jako bazowy format zapisu konfiguracji. Głupota, lenistwo, terminy.

Może było już coś gotowego w bibliotece, a skoro XML to kupa, to po co się wysilać i robić schemat z rigczem.

2
abrakadaber napisał(a):

a dlaczemu nie

<impossible_difficulty_enabled=true/>

A to jest w ogóle poprawny XML? Jeśli jest, to chyba byłoby OK, ale to nowość dla mnie

albo

<key>impossible_difficulty_enabled</key>
<value>true</value>

żeby to jakoś sensownie wyglądało

No właśnie tego formatu kompletnie nie rozumiem.

Czemu

<key>nazwa_klucza</key>
<value>wartość</value>

Skoro można

<nazwa_klucza>
    wartość
</nazwa_klucza>

albo

<nazwa_klucza wartość="" />

albo

<nazwa_klucza>
    <wartość />
</nazwa_klucza>

Tagi <key> oraz <value> nie wnoszą żadnej wartości dodanej, to tylko szum.

slsy napisał(a):

Jako zagorzały przeciwnik XMLa nigdy nie myślałem o tym problemie. IMO to wynika z tego, że XML nie mapuje się na nic, co jest reprezentowane jako struktury danych w językach programowania. JSON jest trywialny do serializacji/parsowania (poza liczbami, ale to dużo mniejszy problem) w dowolnym języku programowania. Z drugiej strony mamy XMLa w którym możemy przedstawić to samo za pomocą różnych konceptów. Mamy node vs attribute, <key>value</key> vs <node><key>key</key><value>value</value></node> nie wiemy jak przedstawiać kolekcję, nie wiemy, czy subnody w danym nodzie to klucze w mapie/strukturze czy cholera wie co.

JSON jest pod tym względem lepszy, ale nie do końca się zgodzę, że taki trywialny.

Po części ten problem występuje także w JSON. Bo jak masz coś takiego:

{
    "blablabla": 1234,
    "pleplepleple": 5678
}

to nie wiesz, czy została tak zserializowana klasa posiadająca dwa pola typu int, czy też słownik mapujący stringi na inty.

Ale mimo to w JSONie chyba raczej nie występuje taka (moim zdaniem) patologia, jak odróżnianie słowników od obiektów poprzez serializację ich w ten sposób:

[
    {
        "key": "blablabla",
        "value": 1234
    },
    {
        "key": "pleplepleple",
        "value": 5678
    }
]

Zakłada się raczej, że wprowadzanie pól o nazwie key i value to tylko szum, zaciemniający znaczenie tego, co się chce serializować. Bo i zresztą wprowadzanie pól o nazwie key czy value nie pomaga w ujednoznacznieniu formatu, ostatecznie może być klasa, która ma takie pola. Nie można zatem zdeserializować JSONa bez wcześniejszej wiedzy, co w tym JSONie może wystąpić i jak się to przekłada na struktury języka programowania.

Tak samo jest z XMLem. Chociaż ma dużo więcej niejednoznaczności niż JSON, podstawowy problem pozostaje ten sam.

slsy napisał(a):

bo nie ma jasnej wykładni/oczywistego sposobu jak rozwiązać dany problem. Po tym przychodzi ktoś inny i zaczyna kopiować to co zobaczył i tak się tworzą różne dialekty.

No więc czemu nie iść drogą najprostszą z możliwych?

Na przykład:

Obiekty serializować tak:

<nazwa_pola>
    wartość_pola
</nazwa_pola
<nazwa_drugiego_pola>
    wartość_drugiego_pola
</nazwa_drugiego_pola>

Słowniki tak:

<klucz>
    wartość
</klucz>
<drugi_klucz>
    wartość
</drugi_klucz>

Listy tak:

<wartość_pierwsza/>
<wartość_druga/>
<wartość_trzecia/>

Itp?

(chyba, że - teraz mi wpadło do głowy - może w XML musi być z góry znana skończona liczba tagów, określona w schema, więc nie można kluczy słowników czy elementów list dawać jako tagów? To by tłumaczyło powszechność tagów typu <key>, <value>, <element> )

3

Próbujesz robić revers enginerig na podstawie tego, co jest w XMLach? Musisz mieć za dużo czasu chyba. Próbujesz oceniać coś od d u p y strony. XML to jest tylko format zapisu, nic ponadto, to co robi z nim programista to tylko wina programisty, a nie samego formatu.
Problem pewnie wziął się bardziej ze słabości parserów tegoż XML gdzie to wszystko jest "nodem" a nie z założeń samego XMLa.

0

Takie formaty jak XML, JSON, CSV itp. lepiej traktować jako przenośne formaty zapisu danych, target dla serializowanych danych i źródło danych, które będziemy deserializować i je jakoś obrabiać. Są to formaty tekstowe, więc można je ręcznie oglądać i edytować, jednak wydaje mi się, że to nie jest efektywna metoda pracy z nimi.

YetAnohterone napisał(a):

Po części ten problem występuje także w JSON. Bo jak masz coś takiego:

{
    "blablabla": 1234,
    "pleplepleple": 5678
}

to nie wiesz, czy została tak zserializowana klasa posiadająca dwa pola typu int, czy też słownik mapujący stringi na inty.

JSON się wziął z JS, więc to się deserializuje w JS jednoznacznie - do obiektu o dwóch właściwościach "blablabla" i "pleplepleple", które posiadają określone wartości (1234 i 5678).

Owszem, deserializacja z JSON do innych języków niż JS nie musi być jednoznaczna. W samym JS też ktoś może zapisywać dane w JSON w specjalny sposób (np. dopisać adnotację typów, żeby było wiadomo instancję jakiej klasy utworzyć przy deserializacji), ale to będzie tylko konwencja.

JSON jest elastyczny, ale prymitywny i nie oczekujmy od niego wiele. Dane w JSONie nie muszą mieć sensu semantycznego (o semantykę samemu trzeba zadbać, jeśli się chce mieć coś extra. Są formaty oparte o JSON, ale żeby je sparsować, trzeba mieć wiedzę o tym, w jaki sposób są w tym JSONie zapisane, no niestety).

Trochę jak alfabet łaciński. Zobaczysz coś w obcym języku, który będzie napisany łacinką (bo systemów pisma też jest wiele na świecie), to jakoś to odczytasz, ale niekoniecznie z dobrą wymową ani niekoniecznie zrozumiesz znaczenie.

Nie można zatem zdeserializować JSONa bez wcześniejszej wiedzy, co w tym JSONie może wystąpić i jak się to przekłada na struktury języka programowania.

Mam wrażenie, że chciałbyś zrobić z JSONa jakieś Protocol buffers (które zawierają więcej informacji o typowaniu). Jednak cechą JSONa jest jego prymitywność (co może być równie dobrze wadą jak i zaletą, zależy jak spojrzeć). Bez jakiegoś zewnętrznego umownego schema albo bez znajomości konkretnego formatu opartego o JSON będziesz miał tylko to, co w tym JSON bezpośrednio jest.

0
  1. XML nie jest kupą, ma poważne zalety, choćby przez posiadanie atrybutów, (uznaną schemę itd ale nie o tym wątek). To raczej JSON sztucznie nadrabia brak, np powszechnym (anty)wzorcem podania sztucznej wartości typu obiektu
    { "type" : "sometype" , "value" : "12345.67" }

  2. kupą w każdym strukturalnym formacie serializacyjnym (wyłączam z wypowiedzi CSV i podobne) jest domniemanie, że dwie sekwencyjnie po sobie wartości tworzą spójną parę. Tego nie da sie zagwarantować (można to ratować, ujmując dwie i tylko dwie wartości w nawias, co @YetAnohterone masz w drugim cytacie kodu). Tym niemniej kupa.

  3. JSON nie jest językiem serializacji idealnie pasujacym do wszystkich języków - wywodzi się i pasuje do JS, który nie jest przesadnie wyposażony w typy

0
ZrobieDobrze napisał(a):
  1. XML nie jest kupą, ma poważne zalety, choćby przez posiadanie atrybutów, (uznaną schemę itd ale nie o tym wątek). To raczej JSON sztucznie nadrabia brak, np powszechnym (anty)wzorcem podania sztucznej wartości typu obiektu
    { "type" : "sometype" , "value" : "12345.67" }

  2. kupą w każdym strukturalnym formacie serializacyjnym (wyłączam z wypowiedzi CSV i podobne) jest domniemanie, że dwie sekwencyjnie po sobie wartości tworzą spójną parę. Tego nie da sie zagwarantować (można to ratować, ujmując dwie i tylko dwie wartości w nawias, co @YetAnohterone masz w drugim cytacie kodu). Tym niemniej kupa.

  3. JSON nie jest językiem serializacji idealnie pasujacym do wszystkich języków - wywodzi się i pasuje do JS, który nie jest przesadnie wyposażony w typy

Ale co Ty porównujesz w ogóle? Markup language, w którym tagi mogą mieć namespace, dzieci i atrybuty vs. tak na prawdę obiekt ze stringami, intami, array'ami i innymi obiektami. To są dwie zupełnie różne rzeczy.

Tak na prawdę jedyne co je łaczy to to że:

a) Są popularne
b) istnieją parsery do nich w wielu językach

i tutaj podobieństwa się kończą.

0
TomRiddle napisał(a):

b) istnieją parsery do nich w wielu językach

I to jest największa zaleta. Standardowy format zapisu danych, który działa w różnych językach(wiec można przenosić/przesyłać dane za ich pomocą)

0
LukeJL napisał(a):
TomRiddle napisał(a):

b) istnieją parsery do nich w wielu językach

I to jest największa zaleta. Standardowy format zapisu danych, który działa w różnych językach(wiec można przenosić/przesyłać dane za ich pomocą)

Co nie zmienia faktu że to jest zaleta dostępności rozwiązań, a nie formatu/języka samego w sobie. Podobną "zaletę" ma PHP, że praktycznie każdy hosting go wspiera, ale czy to znaczy że język sam w sobie jest dobry? questionable.

Teraz dodawanie bibliotek i rozwiązań do projektów jest bardzo powszechne, projekty mają dziesiątki, jak nie setki zależności. dodanie biblioteki do yaml'a do projektu już nie jest problemem.

Rationale

Mi w trzymaniu konfiguracji w XML i JSON właściwie nic nie przeszkadza, tak długo jak ludzie używają jej poprawnie.

Pracowałem kiedyś w projekcie w którym przyjmowaliśmy inputy w JSON'ie, i można je było parsować normalnie. Potem zdażyły się dwa przypadki.

  1. Przypadek jeden, pewien klient wysyłał niepoprawnego JSON'a, tzn nie enkodował białych znaków. Tzn. według specyfikacji powinien wysłać nam {"key":"value\nvalue"} a wysyłał
    {"key":"value
    value"}
    
    po pierwsze nasz parser tego wtedy nie łykał, a po drugie - no jasno widać że to nie powinno działać. Stosowanie tak JSON'a zaciera granicę pomiędzy tym czym nasz projekt jest, a tym czym JSON jest.
  2. Przypadek dwa, w sumie podobny - klient wysyłał JSON'a z apostrofami ' zamiast cudzysłowami ". Ile musieliśmy się natłumaczyć że to działa tylko w JS, ale nie jest standardem JSON.

Także, jak dla mnie - gdyby tylko wszyscy którzy używają tych formatów używali ich zgodnie z przeznaczeniem, i nie szli w nich na kompromisy albo nie zmieniali ich pod swoje widzimisię, to byłoby super. Mógłbym z tym pracować. Ale tak nie jest. Nawet na naszym forum ludzie próbują zmienić to czym jest Markdown, żeby pasowało do ich wizji.

1
ZrobieDobrze napisał(a):
  1. XML nie jest kupą, ma poważne zalety, choćby przez posiadanie atrybutów, (uznaną schemę itd ale nie o tym wątek). To raczej JSON sztucznie nadrabia brak, np powszechnym (anty)wzorcem podania sztucznej wartości typu obiektu
    { "type" : "sometype" , "value" : "12345.67" }

To największa wada według mnie. Jak tworzysz rozszerzalną scheme to nie powinieneś używać atrybutów, bo elementy można łatwiej rozszerzać. Niestety ludzie ich używają, jeśli chodzi o konfigurację czy wymianę danych pomiędzy systemami

  1. kupą w każdym strukturalnym formacie serializacyjnym (wyłączam z wypowiedzi CSV i podobne) jest domniemanie, że dwie sekwencyjnie po sobie wartości tworzą spójną parę. Tego nie da sie zagwarantować (można to ratować, ujmując dwie i tylko dwie wartości w nawias, co @YetAnohterone masz w drugim cytacie kodu). Tym niemniej kupa.

Z JSONowego RFC An array is an ORDERED sequence of zero or more values.. Chyba nie rozumiem problemu, lepiej zagwarantować porządek, bo jak jest nam to potrzebne to mamy to co chcieliśmy, jak nie to możemy przecież olać

  1. JSON nie jest językiem serializacji idealnie pasujacym do wszystkich języków - wywodzi się i pasuje do JS, który nie jest przesadnie wyposażony w typy

Żaden format taki nie jest. Zaletą JSONa jest fakt, że pasuje choć do jednego języka przez co z całą resztą też działa całkiem dobrze. Tego nie da się powiedzieć o XMLu

0
slsy napisał(a):
ZrobieDobrze napisał(a):

Z JSONowego RFC An array is an ORDERED sequence of zero or more values.. Chyba nie rozumiem problemu, lepiej zagwarantować porządek, bo jak jest nam to potrzebne to mamy to co chcieliśmy, jak nie to możemy przecież olać

Array mówisz. Rzecz ewidentnie sekwencyjna.
Ale dwie sąsiednie nazwane wartości (struct w językach) to nie array - a o tym jest watek.

0
ZrobieDobrze napisał(a):

Array mówisz. Rzecz ewidentnie sekwencyjna.
Ale dwie sąsiednie nazwane wartości (struct w językach) to nie array - a o tym jest watek.

Ale w każdym języku działa to tak samo: pola w strukturach to nazwy, nazwa ma być unikatowa w danej strukturze, kolejność pół nie ma żadnego semantycznego znaczenia (poza tym jak C ustawia pola w pamięci ale to akurat jest bardzo słabe)

0
ZrobieDobrze napisał(a):
  1. kupą w każdym strukturalnym formacie serializacyjnym (wyłączam z wypowiedzi CSV i podobne) jest domniemanie, że dwie sekwencyjnie po sobie wartości tworzą spójną parę. Tego nie da sie zagwarantować (można to ratować, ujmując dwie i tylko dwie wartości w nawias, co @YetAnohterone masz w drugim cytacie kodu). Tym niemniej kupa.

Zaraz. Jeśli dobrze rozumiem, twierdzisz, że tagi w XMLu są nieuporządkowane?

Czy kontrprzykładem nie byłby tu XHTML? Ma znaczenie i to duże, czy piszemy

<span>Alice</span> <span>has a</span> <span>cat</span>

Czy też

<span>cat</span> <span>has a</span> <span>Alice</span>
1
somekind napisał(a):

Dobrze, ale po co w ogóle zaglądasz do jakichś losowych xmli na świecie? :P

Może jakaś nowoczesna biblioteka do serializacji tak serializuje, kto wie.

To może być trop z tą nowoczesnością, np pliki .plist z Xcode tak mają. A nic nowocześniejszego niż Apple nie ma.

2

Po kolei:

  1. XML jest gorszy od JSONa, który jest gorszy od YAMLa.
  2. Opisane przez ciebie praktyki nie są czymś powszechnym. Tak, zdarzają się i to zdecydowanie zbyt często, natomiast większość osób jednak trzyma się normalnego zapisu.
  3. Takie wynalazki są zazwyczaj efektem pisania na zaś (overengineering) albo po prostu lenistwa. Tj. zgaduję, że jeśli ktoś miał taką strukturę to zaprojektował ją w ten sposób, żeby mogła mieć całą listę własności, np.
<key>impossible_difficulty_enabled</key>
<true/>
<otherOption/>
<yetAnotherOption/>

Teraz pytanie - dlaczego nie zrobiono tego przez jakąś listę key-value? Ano tradycyjnie - pewnie ktoś chciał mieć dodatkowo XSD, który walidowałby wartości.

1
LukeJL napisał(a):
TomRiddle napisał(a):

b) istnieją parsery do nich w wielu językach

I to jest największa zaleta. Standardowy format zapisu danych, który działa w różnych językach(wiec można przenosić/przesyłać dane za ich pomocą)

Więc lepiej używać JSONa czy (YAMLa do konfguracji) które też są popularne i mają parsery dla wielu języków :P

ZrobieDobrze napisał(a):
  1. JSON nie jest językiem serializacji idealnie pasujacym do wszystkich języków - wywodzi się i pasuje do JS, który nie jest przesadnie wyposażony w typy

Na jakiej podstawie tak mówisz że pasuje tylko do JSa?
IMHO świetnie pasuje do dynamicznie typowanych języków programowania mających listy/tablice i mapy/hashe oraz jeden główny typ na liczby. Do tego opisu pasuje mi też Python i Perl (więcej dynamicznych języków nie używałem za dużo).

W JSONie trochę boli brak Seta. Jeszcze bardziej boli brak koproduktu zwanego też Suma typów, Unia z ograniczeniami czy Jeden z wielu. W językach OOP zwykle rzeźbi się to na dziedziczeniu. W JSONie takiej możliwości nie mamy.

No, ale najbardziej polularna alternatywa (czyli XML) ma wszystkie te same wady JSONa plus jeszcze kilka swoich

2

Myślę, że najlepszą alternatywą jest format TreeStructInfo: https://tsinfo.4programmers.net/ bo eliminuje wszystkie powyższe wady xml-a i jsona jeśli chodzi o przechowywanie konfiguracji. Został stworzony w języku FreePascal, ale pasuje i do innych. Format wymyślony przez @furious programming

Jest to projekt OpenSource i zaletą jest przejrzysty kod źródłowy: https://github.com/furious-programming/TreeStructInfo

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