# perldoc > XML::Generator

---
type: CommandReference
command: XML::Generator
mode: perldoc
section: 
source: perldoc
---

## Quick Reference
- `use XML::Generator ':pretty';` — enable AUTOLOAD and pretty printing
- `my $gen = XML::Generator->new(pretty => 2);` — create object with 2‑space indent
- `$gen->tag_name("content")` — generate `<tag_name>content</tag_name>`
- `$gen->tag_name({ attr => 'val' }, "content")` — add attributes
- `$gen->tag_name(['namespace'], "content")` — default namespace
- `$gen->tag_name(['pre' => 'URI'], { attr => 'val' })` — prefixed namespace + attributes
- `$gen->xmlpi('xml-stylesheet', href => 'style.xsl')` — processing instruction
- `$gen->xmlcdata("unescaped <data>")` — CDATA section

## Name
Perl extension for generating XML

## Synopsis
perl
use XML::Generator ':pretty';

print foo(bar({ baz => 3 }, bam()),
          bar([ 'qux' => '<http://qux.com/>' ],
                "Hey there, world"));

# OR

my $X = XML::Generator->new(':pretty');
print $X->foo($X->bar({ baz => 3 }, $X->bam()),
              $X->bar([ 'qux' => '<http://qux.com/>' ],
                        "Hey there, world"));
## Options

### Constructor options (`new()`)
- `:std, :standard` — equivalent to `escape => 'always', conformance => 'strict'`
- `:strict` — equivalent to `conformance => 'strict'`
- `:pretty[=N]` — pretty print with `N` spaces (default 2), plus `escape => 'always', conformance => 'strict'`
- `namespace` — arrayref for default (`[URI]`) or prefixed (`[prefix => URI, ...]`) namespace; `#default` prefix allowed
- `qualifiedAttributes` / `qualified_attributes` — boolean; prefix attributes with namespace (pre‑0.99 behaviour)
- `escape` — controls escaping of `&`, `<`, `>`, `"` and high‑bit characters  
  Values: `'always'`, `'unescaped'`, `'high-bit'`, `'even-entities'`, `'apos'`; combine with commas (e.g. `'always,high-bit'`)
- `pretty` — integer (spaces per indent) or string (repeat for indent); `"\t"` for tabs
- `conformance` — `'strict'` enables XML checks, special tags, and character filtering
- `filterInvalidChars` / `filter_invalid_chars` — `1` (default in strict) or `0`; filter invalid XML characters
- `allowedXMLTags` / `allowed_xml_tags` — arrayref of tags starting with `xml` allowed in strict mode
- `empty` — empty tag style: `self` (`<tag />`), `compact` (`<tag/>`), `close` (`<tag></tag>`), `ignore` (non‑compliant), `args` (decides based on argument count)
- `version` — default XML version (e.g. `'1.0'`)
- `encoding` — default encoding (e.g. `'UTF-8'`)
- `dtd` — arrayref `[type, name, uri]` for `<!DOCTYPE …>`

### Import arguments (`use`)
- `:import` — export an `AUTOLOAD` that turns undefined subroutines into XML tags
- `:stacked` — same as `:import` but chains with an existing `AUTOLOAD`; your `AUTOLOAD` runs first, return empty list to let XML::Generator continue
- Any other option implies `:import` and is passed to the constructor

## Examples

### Basic generation with pretty printing
perl
use XML::Generator;
my $gen = XML::Generator->new(':pretty');
print $gen->person(
    $gen->name("Bob"),
    $gen->age(34),
    $gen->job("Accountant")
);
### Dynamic tag names
perl
my $tag = "shoe-size";
print $gen->$tag("12 1/2");   # <shoe-size>12 1/2</shoe-size>
### Attributes with `Tie::IxHash` for ordered attributes
perl
use Tie::IxHash;
tie my %attr, 'Tie::IxHash';
%attr = (name => 'Bob', age => 34, job => 'Accountant', 'shoe-size' => '12 1/2');
print $gen->person(\%attr);
# <person name="Bob" age="34" job="Accountant" shoe-size="12 1/2" />
### Namespaces
perl
# Default namespace
print $gen->open(['transaction'], 2000);
# <open xmlns="transaction">2000</open>

# Prefix namespace
print $gen->widget(['wru' => 'http://www.widgets-r-us.com/xml/'],
                   {id => 123}, $gen->contents());
# <wru:widget xmlns:wru="http://www.widgets-r-us.com/xml/" id="123">…</wru:widget>
### Multiple namespaces (RDF example)
perl
my $contactNS = [contact => "http://www.w3.org/2000/10/swap/pim/contact#"];
print $gen->xml(
    $gen->RDF([ rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
                @$contactNS ],
        $gen->Person($contactNS, { 'rdf:about' => "http://…" },
            $gen->fullName($contactNS, 'Eric Miller'),
            $gen->mailbox($contactNS, { 'rdf:resource' => "mailto:em@w3.org" }),
            $gen->personalTitle($contactNS, 'Dr.')
        )
    )
);
### Escaping control
perl
my $gen = XML::Generator->new(escape => 'always,high-bit');
print $gen->foo("<\242>");    # &lt;&#162;&gt;

$gen = XML::Generator->new(escape => 'always,apos');
print $gen->foo({bar => "It's all good"});  # bar="It&apos;s all good"
### Special tags (strict conformance)
perl
my $gen = XML::Generator->new(conformance => 'strict');
print $gen->xmlpi('xml-stylesheet', href => 'style.xsl');   # PI
print $gen->xmlcmnt('This is a comment');                  # <!-- comment -->
print $gen->xmldecl(version => '1.0', encoding => 'UTF-8'); # <?xml?>
print $gen->xmldtd(['html', 'PUBLIC', $pub, $sys]);        # <!DOCTYPE>
print $gen->xmlcdata("raw <data>");                        # <![CDATA[raw <data>]]>
print $gen->xml($gen->html($gen->head($gen->title("Test")))); # final document
### Subclassing (custom tag handler)
perl
package XML::Generator::CustomHTML;
use base 'XML::Generator';

sub table {
    my $self = shift;
    my ($namespace, $attr, @content) =
        $self->XML::Generator::util::parse_args(@_);
    # ... custom formatting ...
    return $self->SUPER::table($attr, $self->tr($self->td(@content)));
}
## See Also
- [XML::Writer](https://metacpan.org/pod/XML::Writer)