# Feature: Parser
Parser lee XML externo y lo convierte al `Document` del core. Sus defaults son
seguros: no resuelve DTD ni entidades externas por defecto y aplica limites de
tamano/profundidad.
## Que aprenderas aqui
[] Parsear strings y readers.
[] Configurar comentarios, CDATA y limites.
[] Entender que entidades se aceptan.
[] Combinar parser con query, schema y writer.
[] Manejar errores de XML invalido.
## Archivo
[] `src/parser/mod.rs`
## Parsear un string
```rust
use xdoc::parser::parse_str;
use xdoc::query::DocumentQueryExt;
let document = parse_str("<Root><Item code=\"A\">one</Item></Root>")?;
let text = document.query("/Root/Item/text()")?.strings();
assert_eq!(text, vec!["one"]);
```
## Parsear un reader
```rust
use std::fs::File;
use xdoc::parser::parse_reader;
let file = File::open("document.xml")?;
let document = parse_reader(file)?;
```
## Configuracion
```rust
use xdoc::parser::{parse_str_with_config, ParserConfig};
let config = ParserConfig::new()
.with_preserve_comments(true)
.with_preserve_cdata(true)
.with_max_document_bytes(1024 * 1024)
.with_max_depth(64)
.with_max_nodes(50_000);
let document = parse_str_with_config("<Root/>", &config)?;
```
Defaults actuales:
[] Comentarios preservados.
[] CDATA preservado.
[] Seguridad configurada por `ParserSecurityConfig::default()`.
## Entidades
El parser acepta entidades predefinidas XML como:
[] `&`
[] `<`
[] `>`
[] `"`
[] `'`
Pero rechaza entidades externas/generales no resueltas por defecto. Esto evita
que XML externo dispare cargas de red o filesystem.
## Namespaces
El parser conserva nombres y namespaces en `QName`.
```rust
let document = parse_str(
r#"<doc:Root xmlns:doc="urn:doc" doc:id="R1"><doc:Child/></doc:Root>"#,
)?;
```
Para consultar ese documento, usa aliases en query:
```rust
use xdoc::query::{DocumentQueryExt, NamespaceContext};
let namespaces = NamespaceContext::new().with_alias("doc", "urn:doc")?;
let result = document.query_with_context("//doc:Child", &namespaces)?;
```
## Errores
```rust
use xdoc::core::ErrorKind;
use xdoc::parser::parse_str;
let error = parse_str("<Root><Unclosed></Root>").expect_err("invalid XML");
assert_eq!(error.kind(), &ErrorKind::Parse);
```
Los errores pueden incluir span cuando el parser puede inferir linea/columna.
## Flujo comun
```rust
let document = parse_str(xml_input)?;
let report = contract.validate(&document)?;
if report.is_valid() {
let output = xdoc::writer::to_string_pretty(
&document,
xdoc::writer::WriterConfig::pretty(),
)?;
}
```
## Errores comunes
[] Intentar parsear multiples roots.
[] Esperar que el parser valide XSD.
[] Usar prefijos de namespace sin declaracion.
[] Esperar que se resuelvan DTD externas.
[] Configurar limites demasiado altos para input no confiable.
## API principal
[] `ParserConfig`
[] `parse_str`
[] `parse_str_with_config`
[] `parse_reader`
[] `parse_reader_with_config`
## Siguiente lectura
[] [query.md](query.md) para consultar el documento.
[] [schema.md](schema.md) para validarlo.
[] [security.md](security.md) para limites.
[Volver al indice](features.md).