XML a JSON v C, C++, Kotlinu a PowerShellu

Volba knihovny závisí na požadovaném modelu a validaci. Tento přehled zachovává stejné pořadí operací jako ostatní jazykové kapitoly a odkazuje na konkrétní dokumentaci.

Autor: Aktualizováno

1. Načtení XML

V C můžeš použít libxml2, v C++ například pugixml. Kotlin na JVM může využít JAXP stejně jako Java. PowerShell pracuje s .NET XmlDocument nebo XmlReader. Parse chybu vždy vyhodnoť před čtením výsledku; pro důvěryhodné malé soubory je DOM pohodlné.

2. Vytvoření XML

Libxml2 vytváří uzly a dokumenty, pugixml nabízí append_child a append_attribute. Kotlin může používat Java DOM createElementNS. V PowerShellu vytvářej uzly .NET API; neskládej libovolný vstup do řetězce XML.

3. Serializace XML

Použij zapisovač vybrané knihovny a kontroluj chyby I/O. Pugixml poskytuje save, JAXP Transformer a .NET Save/XmlWriter. Odsazení může měnit whitespace; u smíšeného obsahu je ověř.

4. DOM

DOM je vhodné pro úpravy stromu. Pugixml má vlastní lehký model odlišný od W3C DOM. Rozlišuj text, komentáře, namespace a životnost uzlů; v C přidělenou paměť uvolň odpovídajícím API, v C++ využij správu životnosti knihovny.

5. Streamové čtení

Libxml2 nabízí xmlTextReader; Kotlin/JVM může použít StAX a PowerShell .NET XmlReader. Pugixml je stromový parser, nikoli řešení pro neomezené streamové čtení. Pro velké vstupy stanov limity a zpracovávej záznamy postupně.

6. XPath

Libxml2 a pugixml mají podporu XPath 1.0. Pugixml XPath pracuje se svým modelem namespace a jmen; nepřenes bez kontroly dotazy z jiného DOM procesoru. Kotlin/JAXP používá podle procesoru XPath, vestavěný JDK podporuje 1.0; .NET XPath také obvykle 1.0.

7. Validace XSD

Libxml2 poskytuje XSD 1.0 validaci. Pugixml není XSD validátor. Kotlin/JVM má JAXP SchemaFactory a PowerShell .NET XmlSchemaSet. Importy schémat řeš řízeným resolverem podle konkrétní knihovny.

8. Bezpečné nastavení XML

Nepřebírej nastavení parseru podle jazyka. U libxml2 hlídej volby DTD, entity a resolver; u JAXP a .NET použij konkrétní zabezpečené konfigurace v jazykových kapitolách. Vypni nepotřebné fáze, omez velikost a hloubku.

9. Načtení JSON

V C například Jansson, v C++ nlohmann/json, v Kotlinu kotlinx.serialization a v PowerShellu ConvertFrom-Json. Odliš dynamický objekt od typovaného modelu. Duplicitní klíče a velká čísla ověř v dokumentaci knihovny a požadavcích aplikace, která data přijímá.

10. Vytvoření JSON

Vytvoř hodnotu knihovnou nebo vlastní datovou strukturou. PowerShell ukázka využívá ordered hashtable pro čitelný výstup; pořadí objektových klíčů ale není významem JSON. Ve vlastní aplikaci rozlišuj null, chybějící položku a prázdné pole.

10. Vytvoření JSON
$data = [ordered]@{ id = "001"; nazev = "XML"; tagy = @("xml", "json") }
$text = $data | ConvertTo-Json -Depth 10
$copy = $text | ConvertFrom-Json
$copy.id

11. Serializace JSON

Jansson nabízí json_dumps, nlohmann/json dump a Kotlin Json.encodeToString pro serializovatelné hodnoty. PowerShell ConvertTo-Json vyžaduje vhodnou hloubku pro vnořená data. Ověř varování, aby se hlubší objekt nezměnil na pouhý textový popis.

12. JSON Schema

Parsování nebo typovaná deserializace není úplná JSON Schema validace. Kotlin může využít JVM validátor, PowerShell .NET knihovnu; pro C/C++ vyber samostatný validátor s požadovaným draftem. Nepředpokládej, že balíček pro JSON zároveň implementuje 2020-12.

Dokumentace knihoven

libxml2 · pugixml · Jansson · nlohmann/json · Kotlin serialization · PowerShell ConvertTo-Json.

C: vytvoření a uložení XML v libxml2

xml-demo.c — celý program
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <stdio.h>
int main(void) {
  xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
  if (!doc) return 1;
  xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "kniha");
  if (!root) { xmlFreeDoc(doc); return 1; }
  xmlDocSetRootElement(doc, root);
  if (!xmlNewProp(root, BAD_CAST "id", BAD_CAST "001") ||
      !xmlNewTextChild(root, NULL, BAD_CAST "nazev", BAD_CAST "XML & JSON")) {
    xmlFreeDoc(doc); return 1;
  }
  int bytes = xmlSaveFormatFileEnc("kniha.xml", doc, "UTF-8", 1);
  xmlFreeDoc(doc);
  if (bytes < 0) return 1;
  puts("kniha.xml ulozena");
  return 0;
}
Kompilace: instalovaná libxml2 a pkg-config
cc xml-demo.c $(pkg-config --cflags --libs libxml-2.0) -o xml-demo
./xml-demo
xmllint --noout kniha.xml

Výstup má atribut id="001" a text XML & JSON; serializátor zapíše ampersand jako entitu. xmlNewTextChild přijímá doslovný text. Přidělený dokument uvolňuje také připojené potomky. Každou alokaci a zápis zkontroluj; nesměšuj xmlFree s uvolňováním paměti jiného API.

Na macOS může být potřeba doplnit include cestu libxml2 z SDK; chybějící hlavička není chyba XML. Pro čtení použij xmlReadFile a kontrolu návratu, pro větší data xmlTextReader. Konkrétní verze libxml2 a resolver rozhodují o přístupu k externím zdrojům; samotná přítomnost NONET není obecný zákaz přístupu k místním souborům. Viz API stromu libxml2 a XXE.

C++: načtení, změna a bezpečný zápis JSON

json-demo.cpp — celý program s nlohmann/json
#include <nlohmann/json.hpp>
#include <fstream>
#include <iostream>
int main() {
  try {
    std::ifstream input("kniha.json");
    if (!input) throw std::runtime_error("Nelze otevrit vstup");
    auto data = nlohmann::json::parse(input);
    if (!data.is_object() || !data.at("id").is_string())
      throw std::runtime_error("Ocekavan objekt s textovym id");
    data["nazev"] = "XML & JSON";
    std::ofstream output("vystup.json");
    if (!output) throw std::runtime_error("Nelze otevrit vystup");
    output << data.dump(2) << '\n';
    output.close();
    if (!output) throw std::runtime_error("Chyba zapisu");
    std::cout << data.at("id").get<std::string>() << '\n';
  } catch (const std::exception& error) {
    std::cerr << error.what() << '\n'; return 1;
  }
}
kniha.json
{"id":"001","nazev":"XML"}
Knihovna musí být v include cestě kompilátoru
c++ -std=c++17 json-demo.cpp -o json-demo
./json-demo

Program vypíše 001 a vytvoří vystup.json s upraveným názvem. Změň id na číslo: kontrola typu hodnoty id skončí chybou. Odeber id: at vyhodí výjimku. Tato kontrola dvou polí není JSON Schema; pro kontrolu dalších polí a pravidel připoj validátor, který podporuje požadovanou verzi JSON Schema. Stromový parser neřeší neomezeně velký vstup: nejdříve omez počet bajtů.

Pro XML můžeš použít pugixml: load_file → kontrola parse_result → child/attribute → save_file → kontrola zápisu. XPath a XML strom neznamenají podporu XSD. Dokumentace parse popisuje výjimky a volitelné chování parseru; zde jsou výjimky zapnuté.

Kotlin/JVM: typovaný model a kotlinx.serialization

build.gradle.kts — samostatný Gradle projekt
plugins {
    kotlin("jvm") version "2.2.20"
    kotlin("plugin.serialization") version "2.2.20"
    application
}
repositories { mavenCentral() }
dependencies { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0") }
kotlin { compilerOptions { jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) } }
java { sourceCompatibility = JavaVersion.VERSION_17; targetCompatibility = JavaVersion.VERSION_17 }
application { mainClass.set("MainKt") }
src/main/kotlin/Main.kt
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.nio.file.Files
import java.nio.file.Path

@Serializable
data class Kniha(val id: String, val nazev: String, val tagy: List<String> = emptyList())

fun main() {
    val format = Json { prettyPrint = true; ignoreUnknownKeys = false }
    val kniha = format.decodeFromString<Kniha>(Files.readString(Path.of("kniha.json")))
    require(kniha.id.isNotBlank()) { "id nesmi byt prazdne" }
    val upravena = kniha.copy(nazev = "XML & JSON")
    Files.writeString(Path.of("vystup.json"), format.encodeToString(upravena))
    println(upravena.id)
}

Použij kniha.json z C++ příkladu, JDK 17+ a Gradle podporující uvedený plugin; spusť gradle run (nebo ./gradlew run, máš-li wrapper). Čekej 001 a soubor s názvem XML & JSON a prázdným seznamem tagy v modelu; výchozí encodeDefaults=false může výchozí pole z výstupu vynechat. Uvedené verze jsou konkrétní sada pro ukázku, ne tvrzení o nejnovějších vydáních.

Odebrání povinného id, číselné id nebo neznámé pole vyvolá chybu deserializace. Prázdný text id odhalí až require. Typovaný model není úplná JSON Schema validace. Pro XML použij JAXP z kapitoly Java; zabezpečení factory platí i v Kotlinu. Plugin generuje serializátor při kompilaci, proto samotné přidání runtime knihovny nestačí. Viz oficiální postup serializace.

PowerShell 7: XML reader a JSON Schema

demo.ps1 — PowerShell 7.4+; spuštění pwsh -File demo.ps1
$ErrorActionPreference = 'Stop'
$settings = [System.Xml.XmlReaderSettings]::new()
$settings.DtdProcessing = [System.Xml.DtdProcessing]::Prohibit
$settings.XmlResolver = $null
$settings.MaxCharactersInDocument = 1MB
$reader = [System.Xml.XmlReader]::Create((Join-Path $PWD 'kniha.xml'), $settings)
try {
    $doc = [System.Xml.XmlDocument]::new()
    $doc.XmlResolver = $null
    $doc.Load($reader)
} finally { $reader.Dispose() }
$doc.DocumentElement.GetAttribute('id')

$schema = @'
{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","required":["id"],"properties":{"id":{"type":"string","minLength":1}}}
'@
'{"id":"001"}' | Test-Json -Schema $schema
'{"id":1}' | Test-Json -Schema $schema -ErrorAction SilentlyContinue
$data = Get-Content -Raw -LiteralPath 'kniha.json' | ConvertFrom-Json
$data.nazev = 'XML & JSON'
$data | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath 'vystup.json' -Encoding utf8

Použij XML vytvořené v C a JSON z C++ příkladu. Čekej id 001, True a False. Reader zakazuje DTD a má limit znaků; DOM stále drží celý dokument v paměti. JSON Schema příklad kontroluje pouze id, další pole povoluje. Test-Json vrací booleovský výsledek, zatímco ConvertFrom-Json vytváří objekt: před úpravou reálného souboru ověř všechna požadovaná pole a jejich omezení.

Verze Windows PowerShell 5.1 má jinou dostupnost příkazů a chování kódování. Zde je použit současný PowerShell 7; neměň Options na povolení komentářů/trailing commas, pokud příjemce vyžaduje standardní JSON. Viz Test-Json.