# 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).