xdoc-rs 0.1.1

Declarative XML engine for Rust
Documentation
# Feature: Transform

Transform convierte un XML en otro XML usando templates programaticos. No es
XSLT. Es una capa Rust sobre `query`, `builder` y `component` para casos donde
quieres extraer datos de un documento fuente y generar otra estructura XML.

## Que aprenderas aqui

[] Crear templates simples.
[] Leer valores del documento fuente.
[] Usar parametros.
[] Repetir salida por resultados de query.
[] Controlar expansion con limites de seguridad.

## Archivo

[] `src/transform/mod.rs`

## Primer transform

Supongamos este XML fuente:

```xml
<Order>
  <ID>O-1</ID>
  <Customer>Ada</Customer>
</Order>
```

Puedes generar un resumen:

```rust
use xdoc::parser::parse_str;
use xdoc::transform::{BindingContext, Template, Transform};
use xdoc::writer::to_string_compact;

let source = parse_str(
    "<Order><ID>O-1</ID><Customer>Ada</Customer></Order>",
)?;

let template = Template::element("Summary")?
    .child(Template::select_text("/Order/ID/text()")?)
    .build();

let output = Transform::new(template).apply_document(
    &source,
    &BindingContext::new(),
)?;

assert_eq!(to_string_compact(&output)?, "<Summary>O-1</Summary>");
```

## Parametros

Los parametros vienen de `BindingContext`.

```rust
use xdoc::transform::{BindingContext, Template, Transform};

let context = BindingContext::new()
    .with_param("status", "accepted");

let template = Template::element("Result")?
    .child(Template::param_text("status"))
    .build();

let document = Transform::new(template).apply_document(&source, &context)?;
```

Si falta el parametro, transform retorna error.

## Atributos desde parametros

```rust
let template = Template::element("Result")?
    .attr_param("status", "status")?
    .child(Template::text("ok"))
    .build();
```

Esto crea un atributo `status` con el valor del parametro `status`.

## Repeat

Usa `Template::repeat` para generar salida por cada nodo seleccionado.

```rust
let item_template = Template::element("Line")?
    .child(Template::select_text("/Item/Name/text()")?)
    .build();

let template = Template::element("Lines")?
    .child(Template::repeat("/Order/Items/Item", item_template)?)
    .build();
```

La template interna se evalua para cada nodo seleccionado. El MVP esta pensado
para transforms simples; si necesitas XSLT completo, usa una herramienta
especializada en la capa superior.

## Namespaces en transform

`BindingContext` permite aliases para queries:

```rust
let context = BindingContext::new()
    .with_namespace("doc", "urn:example:document")?;

let template = Template::element("Title")?
    .child(Template::select_text("/doc:Document/doc:Title/text()")?)
    .build();
```

Para emitir namespaces:

```rust
let template = Template::element("Summary")?
    .namespace("doc", "urn:example:document")?
    .child(Template::text("ok"))
    .build();
```

En el MVP, `Template::element(...)` recibe un nombre local validado. Si necesitas
salida prefijada de forma mas expresiva, construye ese fragment con builder o
`xml!` y luego conviertelo con `Template::from_fragment(...)`.

## Fragments estaticos

Puedes convertir fragments construidos con builder o `xml!` en templates.

```rust
let static_fragment = xdoc::macros::xml! {
    <Footer>Generated</Footer>
}?;

let template = Template::from_fragment(static_fragment)?;
```

## Seguridad

Transform usa `TransformSecurityConfig` para limitar expansiones.

```rust
use xdoc::security::{SecurityLimits, TransformSecurityConfig};
use xdoc::transform::TransformConfig;

let limits = SecurityLimits::new().with_max_transform_expansion(1000);
let config = TransformConfig::new()
    .with_security(TransformSecurityConfig::new().with_limits(limits));

let output = transform.apply_document_with_config(&source, &context, &config)?;
```

## Cuando usar transform

Usa transform si:

[] Tienes un XML fuente y quieres producir otro XML.
[] La transformacion es controlada y pequena.
[] Quieres usar Rust y query, no XSLT.
[] Quieres limites de expansion sencillos.

No lo uses como reemplazo de:

[] XSLT completo.
[] XQuery.
[] Motores de reglas de dominio.

## Errores comunes

[] Usar queries absolutas dentro de un repeat cuando querias seleccionar desde
   el nodo actual.
[] Olvidar aliases de namespace.
[] No configurar limites para input no confiable.
[] Esperar funciones XSLT complejas.

## API principal

[] `BindingContext`
[] `TransformConfig`
[] `Transform`
[] `Template`
[] `ElementTemplate`

## Siguiente lectura

[] [query.md](query.md) para entender las expresiones soportadas.
[] [schema.md](schema.md) para validar antes o despues de transformar.
[] [security.md](security.md) para limites de expansion.

[Volver al indice](features.md).