xdoc-rs 0.1.1

Declarative XML engine for Rust
Documentation
# Feature: Core XML

El core es el modelo comun que usan todas las demas features. Normalmente no lo
usarĂ¡s directamente para crear XML del dia a dia, pero conviene entenderlo
porque parser, builder, macro, query, transform, schema y signature terminan
trabajando sobre los mismos tipos.

## Que aprenderas aqui

[] Que es un `Document`.
[] Como se representan nombres XML y namespaces.
[] Como se reportan errores.
[] Cuando conviene bajar al core en vez de usar builder o macro.

## Archivos

[] `src/core/error.rs`
[] `src/core/names.rs`
[] `src/core/namespace.rs`
[] `src/core/tree.rs`
[] `src/core/mod.rs`

## Modelo mental

Un XML en `xdoc` es un `Document` con nodos internos identificados por `NodeId`.
Cada nodo tiene un `NodeKind`:

[] `Element`
[] `Text`
[] `Comment`
[] `CData`
[] `ProcessingInstruction`

Los elementos tienen:

[] Un `QName`.
[] Atributos.
[] Declaraciones de namespace.
[] Children como `NodeId`.

```text
Document
  root: NodeId
  nodes:
    0: Element(Root)
    1: Element(Child)
    2: Text("value")
```

## Primer ejemplo con core

```rust
use xdoc::core::{Document, QName, XmlResult};
use xdoc::writer::to_string_compact;

fn build() -> XmlResult<String> {
    let mut document = Document::new();
    let root = document.add_root_element(QName::new("Root")?)?;
    let child = document.add_element(root, QName::new("Child")?)?;
    document.add_text(child, "value")?;

    to_string_compact(&document)
}
```

Salida:

```xml
<Root><Child>value</Child></Root>
```

Para XML normal, este ejemplo se escribiria mas comodo con builder o `xml!`.
El core es util cuando necesitas manipular el arbol con control fino.

## Nombres XML

`QName` evita tratar nombres XML como strings sueltos.

```rust
use xdoc::core::QName;

let local = QName::new("ID")?;
let qualified = QName::qualified("doc", "ID", "urn:example:doc")?;
let namespaced = QName::namespaced("ID", "urn:example:default")?;
```

Reglas importantes:

[] `QName::new("ID")` crea un nombre local sin prefijo.
[] `QName::qualified("doc", "ID", "...")` crea `doc:ID`.
[] El prefijo `xml` solo puede apuntar al namespace reservado de XML.
[] El prefijo `xmlns` no se usa como prefijo normal de elementos.
[] La validacion de nombres es conservadora y ASCII en el MVP.

## Namespaces

`NamespaceDeclaration` representa una declaracion `xmlns`.

```rust
use xdoc::core::{NamespaceDeclaration, NamespaceTable};

let default_ns = NamespaceDeclaration::default("urn:default")?;
let prefixed = NamespaceDeclaration::prefixed("doc", "urn:doc")?;

let mut table = NamespaceTable::new();
table.declare(default_ns);
table.declare(prefixed);
```

El writer serializa las declaraciones agregadas al elemento. En builder y
`xml!` normalmente usas helpers mas ergonomicos:

```rust
let root = xdoc::builder::element("Root")?
    .default_namespace("urn:default")?
    .namespace("doc", "urn:doc")?;
```

## Errores

La mayoria de APIs retornan `XmlResult<T>`, que es un alias de
`Result<T, XmlError>`.

```rust
use xdoc::core::{ErrorKind, QName};

let error = QName::new("1Invalid").expect_err("invalid name must fail");
assert_eq!(error.kind(), &ErrorKind::InvalidName);
```

Categorias comunes:

[] `InvalidName`: nombre XML invalido.
[] `InvalidNamespace`: binding de namespace invalido.
[] `InvalidOperation`: operacion que rompe reglas del arbol.
[] `Parse`: XML externo invalido.
[] `Query`: expresion query invalida.
[] `Validation`: contrato no valido o mal definido.
[] `Signature`: error de canonicalizacion, digest, firma o verificacion.

## Cuando usar core directamente

Usa core si:

[] Necesitas construir o inspeccionar nodos a bajo nivel.
[] Estas implementando una nueva feature del motor.
[] Necesitas `NodeId` para una operacion especifica, por ejemplo placement de
   firma.
[] Estas escribiendo pruebas sobre estructura interna.

Prefiere builder o `xml!` si:

[] Solo quieres crear XML.
[] Quieres componer componentes.
[] Quieres una API mas declarativa.

## Errores comunes

[] Crear un segundo root en el mismo `Document`.
[] Intentar agregar children a un nodo que no es elemento.
[] Usar nombres con `:` dentro de `QName::new`; usa `QName::qualified`.
[] Crear un `QName` prefijado sin declarar el namespace al serializar.

## API principal

[] `Document`
[] `NodeId`
[] `Node`
[] `NodeKind`
[] `ElementData`
[] `Attribute`
[] `XmlPath`
[] `QName`
[] `NamespaceUri`
[] `NamespacePrefix`
[] `NamespaceDeclaration`
[] `NamespaceTable`
[] `XmlError`
[] `ErrorKind`
[] `XmlResult<T>`

## Siguiente lectura

[] [builder.md](builder.md) para construir XML sin manipular `NodeId`.
[] [writer.md](writer.md) para serializar el `Document`.
[] [parser.md](parser.md) para crear `Document` desde XML externo.

[Volver al indice](features.md).