<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># TexinfoXML.pm: output tree as Texinfo XML.
#
# Copyright 2011, 2012, 2013 Free Software Foundation, Inc.
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License,
# or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.
# 
# Original author: Patrice Dumas &lt;pertusus@free.fr&gt;

package Texinfo::Convert::TexinfoXML;

use 5.00405;
use strict;

use Texinfo::Convert::Converter;
use Texinfo::Common;
use Texinfo::Convert::Unicode;
# for debugging and adding the original line for some commands
use Texinfo::Convert::Texinfo;
use Data::Dumper;
use Carp qw(cluck);

require Exporter;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
@ISA = qw(Exporter Texinfo::Convert::Converter);

# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.

# This allows declaration       use Texinfo::Convert::TexinfoXML ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
%EXPORT_TAGS = ( 'all' =&gt; [ qw(
  convert
  convert_tree
  output
) ] );

@EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

@EXPORT = qw(
);

$VERSION = '5.1.90';

# XML specific
my %defaults = (
  'ENABLE_ENCODING'      =&gt; 0,
  'SHOW_MENU'            =&gt; 1,
  'EXTENSION'            =&gt; 'xml',
  #'output_perl_encoding' =&gt; 'utf8',
  'OUTPUT_ENCODING_NAME' =&gt; 'utf-8',
  'TEXINFO_DTD_VERSION'  =&gt; '5.0',
  'OUTFILE'              =&gt; undef,
  'SUBDIR'               =&gt; undef,
  'output_format'        =&gt; 'xml',
  'SPLIT'                =&gt; 0,
  'documentlanguage'     =&gt; 'en',
);


# our because it is used in the xml to texi translator
our %commands_formatting = (
           '*' =&gt; 'linebreak',
           ' ' =&gt; ['spacecmd', 'type', 'spc'],
           "\t" =&gt; ['spacecmd', 'type', 'tab'],
           "\n" =&gt; ['spacecmd', 'type', 'nl'],
           '-' =&gt; 'hyphenbreak',  # hyphenation hint
           '|' =&gt; '',  # used in formatting commands @evenfooting and friends
           '/' =&gt; 'slashbreak',
           ':' =&gt; 'noeos',
           '!' =&gt; 'eosexcl',
           '?' =&gt; 'eosquest',
           '.' =&gt; 'eosperiod',
           '@' =&gt; 'arobase',
           '{' =&gt; 'lbrace',
           '}' =&gt; 'rbrace',
           '\\' =&gt; 'backslash',  # should only appear in math

           'TeX' =&gt; 'tex',
           'LaTeX' =&gt; 'latex',
           'bullet' =&gt; 'bullet',
           'copyright'    =&gt; 'copyright',
           'registeredsymbol'   =&gt; 'registered',
           'dots'    =&gt; 'dots',
           'enddots'    =&gt; 'enddots',
           'error'        =&gt; 'errorglyph',
           'expansion'     =&gt; 'expansion',
           'arrow'        =&gt; 'rarr',
           'click'        =&gt; ['click', 'command', 'arrow'],
           'minus'        =&gt; 'minus',
           'point'        =&gt; 'point',
           'print'        =&gt; 'printglyph',
           'result'       =&gt; 'result',
           'l'            =&gt; 'lslash',
           'L'            =&gt; 'Lslash',
           'today'        =&gt; ['today'],
           'comma'        =&gt; 'comma',
           'atchar'       =&gt; 'atchar',
           'lbracechar'   =&gt; 'lbracechar',
           'rbracechar'   =&gt; 'rbracechar',
           'backslashchar' =&gt; 'backslashchar',
           'hashchar'      =&gt; 'hashchar',
);

# use default XML formatting to complete the hash, removing XML
# specific formatting.  This avoids some code duplication.
my %default_xml_commands_formatting = 
    %{$Texinfo::Convert::Converter::default_xml_commands_formatting{'normal'}};

foreach my $command (keys(%default_xml_commands_formatting)) {
  if (!exists($commands_formatting{$command})) {
    if ($default_xml_commands_formatting{$command} ne '') {
      if ($default_xml_commands_formatting{$command} =~ /^&amp;(.*);$/) {
        $commands_formatting{$command} = $1;
      } else {
        die "BUG: Strange xml_commands_formatting: $default_xml_commands_formatting{$command}\n";
      }
    } else {
      $commands_formatting{$command} = '';
    }
  }
}

# Following are XML specific formatting functions.

# format specific.  Used in few places where plain text is used outside
# of attributes.
sub protect_text($$)
{
  my $self = shift;
  my $string = shift;
  return $self-&gt;_protect_text($string);
}

sub _xml_attributes($$)
{
  my $self = shift;
  my $attributes = shift;
  if (ref($attributes) ne 'ARRAY') {
    cluck "attributes not an array($attributes).";
  }
  my $result = '';
  for (my $i = 0; $i &lt; scalar(@$attributes); $i += 2) {
    # this cannot be used, because of formfeed, as in 
    # attribute &lt; which is substituted from &amp;formfeed; is not allowed
    #my $text = $self-&gt;_protect_text($attributes-&gt;[$i+1]);
    my $text = $self-&gt;xml_protect_text($attributes-&gt;[$i+1]);
    # in fact form feed is not allowed at all in XML, even protected
    # and even in xml 1.1 in contrast to what is said on internet.
    # maybe this is a limitation of libxml?
    #$text =~ s/\f/&amp;#12;/g;
    if ($attributes-&gt;[$i] ne 'spaces' 
        and $attributes-&gt;[$i] ne 'trailingspaces') {
      $text =~ s/\f/&amp;attrformfeed;/g;
      # &amp;attrformfeed; resolves to \f so \ are doubled
      $text =~ s/\\/\\\\/g;
    }
    $result .= " $attributes-&gt;[$i]=\"".$text."\"";
  }
  return $result;
}

# format specific
sub element($$$)
{
  my $self = shift;
  my $element_name = shift;
  my $attributes = shift;
  my $result= '&lt;'.$element_name;
  $result .= $self-&gt;_xml_attributes($attributes) if ($attributes);
  $result .= '/&gt;';
  return $result;
}

# format specific
sub open_element($$$)
{
  my $self = shift;
  my $element_name = shift;
  my $attributes = shift;
  my $result= '&lt;'."$element_name";
  $result .= $self-&gt;_xml_attributes($attributes) if ($attributes);
  $result .= '&gt;';
  return $result;
}

# format specific
sub close_element($$)
{
  my $self = shift;
  my $element_name = shift;
  my $result= "&lt;/$element_name&gt;";
  return $result;
}

# format specific
sub format_atom($$)
{
  my $self = shift;
  my $atom = shift;
  if ($commands_formatting{$atom} ne '') {
    return '&amp;'.$commands_formatting{$atom}.';';
  } else {
    return '';
  }
}

# format specific
sub format_comment($$)
{
  my $self = shift;
  my $string = shift;

  return $self-&gt;xml_comment($string);
}

# form feed is not accepted in xml, replace it.
sub _protect_text($$)
{
  my $self = shift;
  my $text = shift;
  my $result = $self-&gt;xml_protect_text($text);
  $result =~ s/\f/&amp;formfeed;/g;
  return $result;
}

# format specific
sub format_text($$)
{
  my $self = shift;
  my $root = shift;
  my $result = $self-&gt;_protect_text($root-&gt;{'text'});
  if (! defined($root-&gt;{'type'}) or $root-&gt;{'type'} ne 'raw') {
    if (!$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}-&gt;[-1]) {
      $result =~ s/``/&amp;textldquo;/g;
      $result =~ s/\'\'/&amp;textrdquo;/g;
      $result =~ s/---/&amp;textmdash;/g;
      $result =~ s/--/&amp;textndash;/g;
      $result =~ s/'/&amp;textrsquo;/g;
      $result =~ s/`/&amp;textlsquo;/g;
    }
  }
  return $result;
}

# output format specific
sub format_header($)
{
  my $self = shift;
  my $encoding = '';
  if ($self-&gt;get_conf('OUTPUT_ENCODING_NAME')
      and $self-&gt;get_conf('OUTPUT_ENCODING_NAME') ne 'utf-8') {
    $encoding = " encoding=\"".$self-&gt;get_conf('OUTPUT_ENCODING_NAME')."\" ";
  }
  my $texinfo_dtd_version = $self-&gt;get_conf('TEXINFO_DTD_VERSION');
  if (!defined($texinfo_dtd_version)) {
    $texinfo_dtd_version = '1.00';
  }

  my $header =  "&lt;?xml version=\"1.0\"${encoding}?&gt;".'
&lt;!DOCTYPE texinfo PUBLIC "-//GNU//DTD TexinfoML V'.$texinfo_dtd_version.'//EN" "http://www.gnu.org/software/texinfo/dtd/'.$texinfo_dtd_version.'/texinfo.dtd"&gt;
'. $self-&gt;open_element('texinfo', ['xml:lang', $self-&gt;get_conf('documentlanguage')])."\n";
  if ($self-&gt;{'output_file'} ne '') {
    my $output_filename = $self-&gt;{'output_filename'};
    $header .= $self-&gt;open_element('filename',['file', $output_filename])
             .$self-&gt;close_element('filename')."\n";
  }
  return $header;
}

# following is not format specific.  Some infos are taken from generic XML, but 
# XML specific formatting is stripped.

my %accents = (
 '=' =&gt; 'macr',
# following are not entities
 'H' =&gt; 'doubleacute',
 'u' =&gt; 'breve',
 'v' =&gt; 'caron',
);

# our because it is used in the xml to texi translator
our %accent_types = (%Texinfo::Convert::Converter::xml_accent_entities, %accents);

# no entity
my @other_accents = ('dotaccent', 'tieaccent', 'ubaraccent', 'udotaccent');
foreach my $accent (@other_accents) {
  $accent_types{$accent} = $accent;
}

my %misc_command_line_attributes = (
  'setfilename' =&gt; 'file',
  'documentencoding' =&gt; 'encoding',
  'verbatiminclude' =&gt; 'file',
  'documentlanguage' =&gt; 'xml:lang',
);

my %misc_command_numbered_arguments_attributes = (
  'definfoenclose' =&gt; [ 'command', 'open', 'close' ],
  'alias' =&gt; [ 'new', 'existing' ],
  'syncodeindex' =&gt; [ 'from', 'to' ],
  'synindex' =&gt; [ 'from', 'to' ],
);

my %misc_commands = %Texinfo::Common::misc_commands;

foreach my $command ('item', 'headitem', 'itemx', 'tab', 
                      keys %Texinfo::Common::def_commands) {
  delete $misc_commands{$command};
}

my %default_args_code_style
  = %Texinfo::Convert::Converter::default_args_code_style;
my %regular_font_style_commands = %Texinfo::Common::regular_font_style_commands;

# our because it is used in the xml to texi translator
our %commands_args_elements = (
  'email' =&gt; ['emailaddress', 'emailname'],
  'uref' =&gt; ['urefurl', 'urefdesc', 'urefreplacement'],
  'url' =&gt; ['urefurl', 'urefdesc', 'urefreplacement'],
  'inforef' =&gt; ['inforefnodename', 'inforefrefname', 'inforefinfoname'],
  'image' =&gt; ['imagefile', 'imagewidth', 'imageheight', 
              'alttext', 'imageextension'],
  'quotation' =&gt; ['quotationtype'],
  'float' =&gt; ['floattype', 'floatname'],
  'itemize' =&gt; ['itemprepend'],
  'enumerate' =&gt; ['enumeratefirst'],
);

foreach my $ref_cmd ('pxref', 'xref', 'ref') {
  $commands_args_elements{$ref_cmd} 
    = ['xrefnodename', 'xrefinfoname', 'xrefprinteddesc', 'xrefinfofile', 
       'xrefprintedname'];
}

foreach my $explained_command (keys(%Texinfo::Common::explained_commands)) {
  $commands_args_elements{$explained_command} = ["${explained_command}word",
                                                 "${explained_command}desc"];
}

foreach my $inline_command (keys(%Texinfo::Common::inline_commands)) {
  $commands_args_elements{$inline_command} = ["${inline_command}format",
                                              "${inline_command}content"];
}

my $inline_command = 'inlinefmtifelse';
$commands_args_elements{$inline_command} = ["${inline_command}format",
             "${inline_command}contentif", "${inline_command}contentelse"];

my %commands_elements;
foreach my $command (keys(%Texinfo::Common::brace_commands)) {
  $commands_elements{$command} = [$command];
  if ($commands_args_elements{$command}) {
    push @{$commands_elements{$command}}, @{$commands_args_elements{$command}};
  }
}

my %defcommand_name_type = (
 'deffn'     =&gt; 'function',
 'defvr'     =&gt; 'variable',
 'deftypefn' =&gt; 'function',
 'deftypeop' =&gt; 'operation',
 'deftypevr' =&gt; 'variable',
 'defcv'     =&gt; 'classvar',
 'deftypecv' =&gt; 'classvar',
 'defop'     =&gt; 'operation',
 'deftp'     =&gt; 'datatype',
);

my %ignored_types;
foreach my $type (
            # those are put as spaces in the corresponding @-command
            'empty_spaces_after_command',
            'empty_spaces_before_argument',
  ) {
  $ignored_types{$type} = 1;
}

# this is used in IXIN, to ignore everything before first node.
sub _set_ignored_type($$)
{
  my $self = shift;
  my $type = shift;

  $ignored_types{$type} = 1;
}

my %type_elements = (
  'paragraph' =&gt; 'para',
  'preformatted' =&gt; 'pre',
  'menu_entry' =&gt; 'menuentry',
  'menu_entry_node' =&gt; 'menunode',
  'menu_comment' =&gt; 'menucomment',
  'menu_entry_description' =&gt; 'menudescription',
  'menu_entry_name' =&gt; 'menutitle',
  'preamble' =&gt; 'preamble',
  'table_item' =&gt; 'tableitem',
  'table_entry' =&gt; 'tableentry',
  'table_term' =&gt; 'tableterm',
  'row' =&gt; 'row',
  'multitable_head' =&gt; 'thead',
  'multitable_body' =&gt; 'tbody',
  'def_item' =&gt; 'definitionitem',
  'before_item' =&gt; 'beforefirstitem',
);

my %default_context_block_commands = (
  'float' =&gt; 1,
);

sub converter_defaults($$)
{
  return %defaults;
}

sub converter_initialize($)
{
  my $self = shift;

  $self-&gt;{'document_context'} = [{'monospace' =&gt; [0]}];
  $self-&gt;{'context_block_commands'} = {%default_context_block_commands};
  foreach my $raw (keys (%Texinfo::Common::format_raw_commands)) {
    $self-&gt;{'context_block_commands'}-&gt;{$raw} = 1
         if $self-&gt;{'expanded_formats_hash'}-&gt;{$raw};
  } 
  if ($self-&gt;{'parser'}) {
    my ($index_names, $merged_indices)
       = $self-&gt;{'parser'}-&gt;indices_information();
    $self-&gt;{'index_names'} = $index_names;
  }
}

sub output($$)
{
  my $self = shift;
  my $root = shift;

  $self-&gt;_set_outfile();
  return undef unless $self-&gt;_create_destination_directory();

  my $fh;
  if (! $self-&gt;{'output_file'} eq '') {
    $fh = $self-&gt;Texinfo::Common::open_out($self-&gt;{'output_file'});
    if (!$fh) {
      $self-&gt;document_error(sprintf($self-&gt;__("could not open %s for writing: %s"),
                                    $self-&gt;{'output_file'}, $!));
      return undef;
    }
  }

  $self-&gt;_set_global_multiple_commands(-1);

  my $result = '';
  $result .= $self-&gt;_output_text($self-&gt;format_header(), $fh);
  if ($self-&gt;get_conf('USE_NODES')) {
    $result .= $self-&gt;convert_document_nodes($root, $fh);
  } else {
    $result .= $self-&gt;convert_document_sections($root, $fh);
  }
  $result .= $self-&gt;_output_text($self-&gt;close_element('texinfo')."\n", $fh);
  if ($fh and $self-&gt;{'output_file'} ne '-') {
    $self-&gt;register_close_file($self-&gt;{'output_file'});
    if (!close ($fh)) {
      $self-&gt;document_error(sprintf($self-&gt;__("error on closing %s: %s"),
                                    $self-&gt;{'output_file'}, $!));
    }
  }

  return $result;
}

sub _format_command($$)
{
  my $self = shift;
  my $command = shift;

  if (! ref($commands_formatting{$command})) {
    return $self-&gt;format_atom($command);
  } else {
    my @spec = @{$commands_formatting{$command}};
    my $element_name = shift @spec;
    return $self-&gt;element($element_name, \@spec);
  }
}

sub _index_entry($$)
{
  my $self = shift;
  my $root = shift;
  if ($root-&gt;{'extra'} and $root-&gt;{'extra'}-&gt;{'index_entry'}) {
    my $index_entry = $root-&gt;{'extra'}-&gt;{'index_entry'};
    my $attribute = ['index', $index_entry-&gt;{'index_name'}];
    push @$attribute, ('number', $index_entry-&gt;{'number'})
        if (defined($index_entry-&gt;{'number'}));
    # in case the index is not a default index, or the style of the
    # entry (in code or not) is not the default for this index
    if ($self-&gt;{'index_names'}) {
      my $in_code = $self-&gt;{'index_names'}-&gt;{$index_entry-&gt;{'index_name'}}-&gt;{'in_code'};
      if (!$Texinfo::Common::index_names{$index_entry-&gt;{'index_name'}}
          or $in_code != $Texinfo::Common::index_names{$index_entry-&gt;{'index_name'}}-&gt;{'in_code'}) {
        push @$attribute, ('incode', $in_code);
      }
      if ($self-&gt;{'index_names'}-&gt;{$index_entry-&gt;{'index_name'}}-&gt;{'merged_in'}) {
        push @$attribute, ('mergedindex', 
         $self-&gt;{'index_names'}-&gt;{$index_entry-&gt;{'index_name'}}-&gt;{'merged_in'});
      }
    }
    my $result = $self-&gt;open_element('indexterm', $attribute);
    push @{$self-&gt;{'document_context'}}, {'monospace' =&gt; [0]};
    $self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}-&gt;[-1] = 1
      if ($index_entry-&gt;{'in_code'});
    $result .= $self-&gt;_convert({'contents' =&gt; $index_entry-&gt;{'content'}});
    pop @{$self-&gt;{'document_context'}};
    $result .= $self-&gt;close_element('indexterm');
    return $result;
  }
  return '';
}

sub _infoenclose_attribute($$) {
  my $self = shift;
  my $root = shift;
  my @attribute = ();
  return @attribute if (!$root-&gt;{'extra'});
  push @attribute, ('begin', $root-&gt;{'extra'}-&gt;{'begin'})
    if (defined($root-&gt;{'extra'}-&gt;{'begin'}));
  push @attribute, ('end', $root-&gt;{'extra'}-&gt;{'end'})
    if (defined($root-&gt;{'extra'}-&gt;{'end'}));
  return @attribute;
}

sub _accent($$;$$$)
{
  my $self = shift;
  my $text = shift;
  my $root = shift;
  my $in_upper_case = shift;
  my $attributes = shift;
  $attributes = [] if (!defined($attributes));

  unshift @$attributes, ('type', $accent_types{$root-&gt;{'cmdname'}});
  my $result = $self-&gt;open_element('accent', $attributes);
  $result .= $text;
  $result .= $self-&gt;close_element('accent');
  return $result;
}

sub convert($$;$)
{
  my $self = shift;
  my $root = shift;
  my $fh = shift;
  
  return $self-&gt;convert_document_sections($root, $fh);
}

sub convert_tree($$)
{
  my $self = shift;
  my $root = shift;

  return $self-&gt;_convert($root);
}

sub _protect_in_spaces($)
{
  my $text = shift;
  $text =~ s/\n/\\n/g;
  $text =~ s/\f/\\f/g;
  return $text;
}

sub _leading_spaces($)
{
  my $root = shift;
  if ($root-&gt;{'extra'} and $root-&gt;{'extra'}-&gt;{'spaces_after_command'}
      and $root-&gt;{'extra'}-&gt;{'spaces_after_command'}-&gt;{'type'} eq 'empty_spaces_after_command') {
    return ('spaces', _protect_in_spaces(
         $root-&gt;{'extra'}-&gt;{'spaces_after_command'}-&gt;{'text'}));
  } else {
    return ();
  }
}

sub _leading_spaces_before_argument($)
{
  my $root = shift;
  if ($root-&gt;{'extra'} and $root-&gt;{'extra'}-&gt;{'spaces_before_argument'}
      and $root-&gt;{'extra'}-&gt;{'spaces_before_argument'}-&gt;{'type'} eq 'empty_spaces_before_argument'
      and $root-&gt;{'extra'}-&gt;{'spaces_before_argument'}-&gt;{'text'} ne '') {
    return ('spaces', _protect_in_spaces(
                 $root-&gt;{'extra'}-&gt;{'spaces_before_argument'}-&gt;{'text'}));
  } else {
    return ();
  }
}

sub _end_line_spaces($$)
{
  my $root = shift;
  my $type = shift;

  my $end_spaces = undef;
  if ($root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}) {
    my $index = -1;
    if ($root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[-1]-&gt;{'cmdname'}
        and ($root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[-1]-&gt;{'cmdname'} eq 'c' 
             or $root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[-1]-&gt;{'cmdname'} eq 'comment')) {
      $index = -2;
    }
    if ($root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[$index]
        and $root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[$index]-&gt;{'type'}
        and $root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[$index]-&gt;{'type'} eq $type
        and defined($root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[$index]-&gt;{'text'})
        and $root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[$index]-&gt;{'text'} !~ /\S/) {
      $end_spaces = $root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[$index]-&gt;{'text'};
      chomp $end_spaces;
    }
  }
  return $end_spaces;
}

sub _arg_line($)
{
  my $self = shift;
  my $root = shift;
  if ($root-&gt;{'extra'} and defined($root-&gt;{'extra'}-&gt;{'arg_line'})) {
    my $line = $root-&gt;{'extra'}-&gt;{'arg_line'};
    chomp($line);
    if ($line ne '') {
      return ('line', $line);
    }
  } 
  return ();
}

sub _trailing_spaces_arg($$)
{
  my $self = shift;
  my $root = shift;
  
  my @spaces = $self-&gt;_collect_leading_trailing_spaces_arg($root);
  if (defined($spaces[1])) {
    chomp($spaces[1]);
    if ($spaces[1] ne '') {
      return ('trailingspaces', _protect_in_spaces($spaces[1]));
    }
  }
  return ();
}

sub _leading_spaces_arg($$)
{
  my $self = shift;
  my $root = shift;

  my @result = ();
  my @spaces = $self-&gt;_collect_leading_trailing_spaces_arg($root);
  if (defined($spaces[0]) and $spaces[0] ne '') {
    @result = ('spaces', _protect_in_spaces($spaces[0]));
  }
  return @result;
}

sub _leading_trailing_spaces_arg($$)
{
  my $self = shift;
  my $root = shift;

  my @result;
  my @spaces = $self-&gt;_collect_leading_trailing_spaces_arg($root);
  if (defined($spaces[0]) and $spaces[0] ne '') {
    push @result, ('spaces', _protect_in_spaces($spaces[0]));
  }
  if (defined($spaces[1])) {
    chomp($spaces[1]);
    if ($spaces[1] ne '') {
      push @result, ('trailingspaces', _protect_in_spaces($spaces[1]));
    }
  }
  return @result;
}

sub _texinfo_line($$)
{
  my $self = shift;
  my $root = shift;

  my ($comment, $tree) = Texinfo::Convert::Converter::_tree_without_comment(
                                                                        $root);
  my $line = Texinfo::Convert::Texinfo::convert($tree);
  chomp($line);
  if ($line ne '') {
    return ('line', $line);
  } else {
    return ();
  }
}

my @node_directions = ('Next', 'Prev', 'Up');

# not used here, but it is consistent with other %commands_args_elements
# entries and may be used by XML to Texinfo converters
$commands_args_elements{'node'} = ['nodename'];
foreach my $direction (@node_directions) {
  push @{$commands_args_elements{'node'}}, 'node'.lc($direction);
}

sub _convert($$;$);

sub _convert($$;$)
{
  my $self = shift;
  my $root = shift;

  if (0) {
  #if (1) { #}
    print STDERR "root\n";
    print STDERR "  Command: $root-&gt;{'cmdname'}\n" if ($root-&gt;{'cmdname'});
    print STDERR "  Type: $root-&gt;{'type'}\n" if ($root-&gt;{'type'});
    print STDERR "  Text: $root-&gt;{'text'}\n" if (defined($root-&gt;{'text'}));
    #print STDERR "  Special def_command: $root-&gt;{'extra'}-&gt;{'def_command'}\n"
    #  if (defined($root-&gt;{'extra'}) and $root-&gt;{'extra'}-&gt;{'def_command'});
  }

  return '' if ($root-&gt;{'type'} and $ignored_types{$root-&gt;{'type'}});
  my $result = '';
  if (defined($root-&gt;{'text'})) {
    if ($self-&gt;{'document_context'}-&gt;[-1]-&gt;{'raw'}) {
      # ignore the newline at the end of the @xml line, and the last in xml
      if ($root-&gt;{'type'} and ($root-&gt;{'type'} eq 'empty_line_after_command'
                               or $root-&gt;{'type'} eq 'last_raw_newline')) {
        return '';
      } else {
        return $root-&gt;{'text'};
      }
    } elsif ($root-&gt;{'type'} 
             and $root-&gt;{'type'} eq 'empty_line_after_command'
             and $root-&gt;{'extra'}-&gt;{'command'}) {
      my $command_name = $root-&gt;{'extra'}-&gt;{'command'}-&gt;{'cmdname'};
      
      if ($Texinfo::Common::format_raw_commands{$command_name} and 
          $self-&gt;{'expanded_formats_hash'}-&gt;{$command_name}) {
        return '';
      }
    }
    $result = $self-&gt;format_text($root);
    return $result;
  }
  my @close_elements;
  if ($root-&gt;{'cmdname'}) {
    if (defined($commands_formatting{$root-&gt;{'cmdname'}})) {
      if ($root-&gt;{'cmdname'} eq 'click' 
          and $root-&gt;{'extra'} 
          and defined($root-&gt;{'extra'}-&gt;{'clickstyle'})) {
        return $self-&gt;element('click', ['command', $root-&gt;{'extra'}-&gt;{'clickstyle'}]);;
      }
      if ($self-&gt;{'itemize_line'} and $root-&gt;{'type'} 
          and $root-&gt;{'type'} eq 'command_as_argument'
          and !$root-&gt;{'args'}) {
        return $self-&gt;element('formattingcommand', ['command', $root-&gt;{'cmdname'}]);
      }
      return $self-&gt;_format_command($root-&gt;{'cmdname'});
    } elsif ($accent_types{$root-&gt;{'cmdname'}}) {
      if ($self-&gt;get_conf('ENABLE_ENCODING')) {
        return $self-&gt;convert_accents($root, \&amp;_accent);
      } else {
        my $attributes = [];
        if (!$root-&gt;{'args'}) {
          $result = '';
        } else {
          $result = $self-&gt;_convert($root-&gt;{'args'}-&gt;[0]);
          if ($root-&gt;{'extra'} and $root-&gt;{'extra'}-&gt;{'spaces'}) {
            push @$attributes,  ('spaces', $root-&gt;{'extra'}-&gt;{'spaces'});
          }
          if ($root-&gt;{'args'}-&gt;[0]-&gt;{'type'} eq 'following_arg') {
             push @$attributes, ('bracketed', 'off');
          }
        }
        return $self-&gt;_accent($result, $root,  undef, $attributes);
      }
    } elsif ($root-&gt;{'cmdname'} eq 'item' or $root-&gt;{'cmdname'} eq 'itemx'
             or $root-&gt;{'cmdname'} eq 'headitem' or $root-&gt;{'cmdname'} eq 'tab') {
      if ($root-&gt;{'cmdname'} eq 'item'
          and $root-&gt;{'parent'}-&gt;{'cmdname'}
          and ($root-&gt;{'parent'}-&gt;{'cmdname'} eq 'itemize'
               or $root-&gt;{'parent'}-&gt;{'cmdname'} eq 'enumerate')) {
        $result .= $self-&gt;open_element('listitem', [_leading_spaces($root)]);
        if ($root-&gt;{'parent'}-&gt;{'cmdname'} eq 'itemize'
            and $root-&gt;{'parent'}-&gt;{'extra'} 
            and $root-&gt;{'parent'}-&gt;{'extra'}-&gt;{'block_command_line_contents'}
            and $root-&gt;{'parent'}-&gt;{'extra'}-&gt;{'block_command_line_contents'}-&gt;[0]) {
          $result .= $self-&gt;open_element('prepend')
            .$self-&gt;_convert({'contents' 
        =&gt; $root-&gt;{'parent'}-&gt;{'extra'}-&gt;{'block_command_line_contents'}-&gt;[0]})
            .$self-&gt;close_element('prepend');
        }
        unshift @close_elements, 'listitem';
      } elsif (($root-&gt;{'cmdname'} eq 'item' or $root-&gt;{'cmdname'} eq 'itemx')
               and $root-&gt;{'parent'}-&gt;{'type'} 
               and $root-&gt;{'parent'}-&gt;{'type'} eq 'table_term') {
        my $table_command = $root-&gt;{'parent'}-&gt;{'parent'}-&gt;{'parent'};
        my $format_item_command;
        my $attribute = [];
        if ($table_command-&gt;{'extra'} 
            and $table_command-&gt;{'extra'}-&gt;{'command_as_argument'}) {
          $format_item_command 
            = $table_command-&gt;{'extra'}-&gt;{'command_as_argument'}-&gt;{'cmdname'};
          $attribute 
           = [$self-&gt;_infoenclose_attribute($table_command-&gt;{'extra'}-&gt;{'command_as_argument'})];
        }
        $result .= $self-&gt;open_element($root-&gt;{'cmdname'}, [_leading_spaces($root)]);
        if ($format_item_command) {
          $result .=  $self-&gt;open_element('itemformat', ['command', $format_item_command, @$attribute]);
        }
        $result .= $self-&gt;_index_entry($root);
        my $in_code;
        $in_code = 1
          if ($format_item_command 
              and defined($default_args_code_style{$format_item_command})
              and $default_args_code_style{$format_item_command}-&gt;[0]);
        my $in_monospace_not_normal;
        if ($format_item_command) {
          if (defined($default_args_code_style{$format_item_command})
              and $default_args_code_style{$format_item_command}-&gt;[0]) {
            $in_monospace_not_normal = 1;
          } elsif ($regular_font_style_commands{$format_item_command}) {
            $in_monospace_not_normal = 0;
          }
        }
        push @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}}, 
          $in_monospace_not_normal
            if (defined($in_monospace_not_normal));

        $result .= $self-&gt;_convert($root-&gt;{'args'}-&gt;[0]);
        pop @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}} 
          if (defined($in_monospace_not_normal));
        chomp ($result);
        if ($format_item_command) {
          $result .= $self-&gt;close_element('itemformat');
        }
        $result .= $self-&gt;close_element($root-&gt;{'cmdname'})."\n";
      } else {
        unless (($root-&gt;{'cmdname'} eq 'item' 
                     or $root-&gt;{'cmdname'} eq 'headitem'
                     or $root-&gt;{'cmdname'} eq 'tab')
                    and $root-&gt;{'parent'}-&gt;{'type'}
                    and $root-&gt;{'parent'}-&gt;{'type'} eq 'row') {
          print STDERR "BUG: multitable cell command not in a row "
            .Texinfo::Parser::_print_current($root);
        }
        
        $result .= $self-&gt;open_element('entry', ['command', 
               $root-&gt;{'cmdname'}, _leading_spaces($root)]);
        unshift @close_elements, 'entry';
      }
    } elsif ($root-&gt;{'type'} and $root-&gt;{'type'} eq 'index_entry_command') {
      my $element;
      my $attribute = [];
      if (exists $Texinfo::Common::misc_commands{$root-&gt;{'cmdname'}}) {
        $element = $root-&gt;{'cmdname'};
      } else {
        $element = 'indexcommand';
        $attribute = ['command', $root-&gt;{'cmdname'}];
      }
      push @$attribute, ('index', $root-&gt;{'extra'}-&gt;{'index_entry'}-&gt;{'index_name'});
      push @$attribute, _leading_spaces($root);
      my $end_line;
      if ($root-&gt;{'args'}-&gt;[0]) {
        $end_line = $self-&gt;_end_line_or_comment($root-&gt;{'args'}-&gt;[0]-&gt;{'contents'});
      } else {
        # May that happen?
        $end_line = '';
      }
      return $self-&gt;open_element($element, ${attribute}).
        $self-&gt;_index_entry($root).$self-&gt;close_element($element).${end_line};
    } elsif (exists($misc_commands{$root-&gt;{'cmdname'}})) {
      my $command = $root-&gt;{'cmdname'};
      my $type = $misc_commands{$root-&gt;{'cmdname'}};
      if ($type eq 'text') {
        return '' if ($root-&gt;{'cmdname'} eq 'end');
        my $attribute;
        if ($misc_command_line_attributes{$root-&gt;{'cmdname'}}) {
          if ($root-&gt;{'extra'} and defined($root-&gt;{'extra'}-&gt;{'text_arg'})) {
            push @$attribute, ($misc_command_line_attributes{$root-&gt;{'cmdname'}},
                  $root-&gt;{'extra'}-&gt;{'text_arg'});
          }
        }
        my ($arg, $end_line)
            = $self-&gt;_convert_argument_and_end_line($root-&gt;{'args'}-&gt;[0]);
        push @$attribute, _leading_spaces($root);
        return $self-&gt;open_element($command, $attribute).$arg
                .$self-&gt;close_element($command).${end_line};
      } elsif ($type eq 'line') {
        if ($root-&gt;{'cmdname'} eq 'node') {
          my $nodename;
          if (defined($root-&gt;{'extra'}-&gt;{'normalized'})) {
            $nodename = $root-&gt;{'extra'}-&gt;{'normalized'};
          } else {
            $nodename = '';
          }
          # FIXME avoid protection, here?
          $result .= $self-&gt;open_element('node', ['name', $nodename, _leading_spaces($root)]);
          push @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}}, 1;
          $result .= $self-&gt;open_element('nodename', 
            [$self-&gt;_trailing_spaces_arg($root-&gt;{'args'}-&gt;[0])])
             .$self-&gt;_convert({'contents' =&gt; $root-&gt;{'extra'}-&gt;{'node_content'}})
             .$self-&gt;close_element('nodename');
          # first arg is the node name.
          my $direction_index = 1;
          my $pending_empty_directions = '';
          foreach my $direction(@node_directions) {
            my $element = 'node'.lc($direction);
            if ($root-&gt;{'node_'.lc($direction)}) {
              my $node_direction = $root-&gt;{'node_'.lc($direction)};
              my $node_name = '';
              my $attribute = [];
              if (! defined($root-&gt;{'extra'}-&gt;{'nodes_manuals'}-&gt;[$direction_index])) {
                push @$attribute, ('automatic', 'on');
              }
              if ($root-&gt;{'args'}-&gt;[$direction_index]) {
                push @$attribute, $self-&gt;_leading_trailing_spaces_arg(
                                 $root-&gt;{'args'}-&gt;[$direction_index]);
              }
              if ($node_direction-&gt;{'extra'}-&gt;{'manual_content'}) {
                $node_name .= $self-&gt;_convert({
                             'contents' =&gt; [{'text' =&gt; '('},
                             @{$node_direction-&gt;{'extra'}-&gt;{'manual_content'}},
                                          {'text' =&gt; ')'}]});
              }
              if ($node_direction-&gt;{'extra'}-&gt;{'node_content'}) {
                $node_name .= Texinfo::Common::normalize_top_node_name($self-&gt;_convert({
                  'contents' =&gt; $node_direction-&gt;{'extra'}-&gt;{'node_content'}}));
              }
              $result .= "$pending_empty_directions".
                $self-&gt;open_element($element, ${attribute}).$node_name.
                $self-&gt;close_element($element);
              $pending_empty_directions = '';
            } else {
              if ($root-&gt;{'args'}-&gt;[$direction_index]) {
                my $spaces_attribute = $self-&gt;_leading_trailing_spaces_arg(
                                 $root-&gt;{'args'}-&gt;[$direction_index]);
                $pending_empty_directions .= $self-&gt;open_element($element,
                    [$self-&gt;_leading_trailing_spaces_arg(
                                 $root-&gt;{'args'}-&gt;[$direction_index])])
                            .$self-&gt;close_element($element);
              }
            }
            $direction_index++;
          }
          my $end_line;
          if ($root-&gt;{'args'}-&gt;[0]) {
            $end_line 
              = $self-&gt;_end_line_or_comment($root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'});
          } else {
            $end_line = "\n";
          }
          if (! $self-&gt;get_conf('USE_NODES')) {
            $result .= $self-&gt;close_element('node');
          }
          $result .= ${end_line};
          pop @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}};
        } elsif ($Texinfo::Common::root_commands{$root-&gt;{'cmdname'}}) {
          my $attribute = [_leading_spaces($root)];
          $command = $self-&gt;_level_corrected_section($root);
          if ($command ne $root-&gt;{'cmdname'}) {
            unshift @$attribute, ('originalcommand', $root-&gt;{'cmdname'});
          }
          $result .= $self-&gt;open_element($command, $attribute);
          my $closed_section_element;
          if ($self-&gt;get_conf('USE_NODES')) {
            $closed_section_element = $self-&gt;close_element($command);
          } else {
            $closed_section_element = '';
          }

          if ($root-&gt;{'args'} and $root-&gt;{'args'}-&gt;[0]) {
            my ($arg, $end_line)
              = $self-&gt;_convert_argument_and_end_line($root-&gt;{'args'}-&gt;[0]);
            $result .= $self-&gt;open_element('sectiontitle').$arg
                      .$self-&gt;close_element('sectiontitle')
                      .$closed_section_element.$end_line;
          } else {
            $result .= $closed_section_element;
          }
        } else {
          my $attribute = [_leading_spaces($root)];
          if ($root-&gt;{'cmdname'} eq 'listoffloats' and $root-&gt;{'extra'} 
              and $root-&gt;{'extra'}-&gt;{'type'} 
              and defined($root-&gt;{'extra'}-&gt;{'type'}-&gt;{'normalized'})) {
            unshift @$attribute, ('type', $root-&gt;{'extra'}-&gt;{'type'}-&gt;{'normalized'});
          }
          my ($arg, $end_line)
            = $self-&gt;_convert_argument_and_end_line($root-&gt;{'args'}-&gt;[0]);
          return $self-&gt;open_element($command, ${attribute}).$arg
               .$self-&gt;close_element($command).$end_line;
        }
      } elsif ($type eq 'skipline') {
        # the command associated with an element is closed at the end of the
        # element. @bye is withing the element, but we want it to appear after
        # the comand closing.  So we delay the output of @bye, and store it.
        if ($root-&gt;{'cmdname'} eq 'bye' and $root-&gt;{'parent'}
            and $root-&gt;{'parent'}-&gt;{'type'}
            and $root-&gt;{'parent'}-&gt;{'type'} eq 'element'
            and !($root-&gt;{'parent'}-&gt;{'extra'}
                  and ($root-&gt;{'parent'}-&gt;{'extra'}-&gt;{'no_section'}
                       or $root-&gt;{'parent'}-&gt;{'extra'}-&gt;{'no_node'}))) {
          #print STDERR "$root-&gt;{'parent'} $root-&gt;{'parent'}-&gt;{'type'}\n";
          $self-&gt;{'pending_bye'} = $self-&gt;open_element($command)
                    .$self-&gt;close_element($command)."\n";
          return '';
        }
        my $attribute = [];
        if ($root-&gt;{'args'} and $root-&gt;{'args'}-&gt;[0] 
            and defined($root-&gt;{'args'}-&gt;[0]-&gt;{'text'})) {
          my $line = $root-&gt;{'args'}-&gt;[0]-&gt;{'text'};
          chomp($line);
          $attribute = ['line', $line]
             if ($line ne '');
        }
        return $self-&gt;open_element($command, $attribute)
                 .$self-&gt;close_element($command)."\n";
      } elsif ($type eq 'noarg' or $type eq 'skipspace') {
        my $spaces = '';
        $spaces = $root-&gt;{'extra'}-&gt;{'spaces_after_command'}-&gt;{'text'}
          if ($root-&gt;{'extra'} and $root-&gt;{'extra'}-&gt;{'spaces_after_command'}
              and $root-&gt;{'extra'}-&gt;{'spaces_after_command'}-&gt;{'type'} eq 'empty_spaces_after_command');
        return $self-&gt;open_element($command)
                .$self-&gt;close_element($command).$spaces;
      } elsif ($type eq 'special') {
        if ($root-&gt;{'cmdname'} eq 'clear' or $root-&gt;{'cmdname'} eq 'set') {
          my $attribute = [];
          if ($root-&gt;{'args'} and $root-&gt;{'args'}-&gt;[0]
              and defined($root-&gt;{'args'}-&gt;[0]-&gt;{'text'})) {
            push @$attribute, ('name', $root-&gt;{'args'}-&gt;[0]-&gt;{'text'});
          }
          my $value = '';
          if ($root-&gt;{'cmdname'} eq 'set' and $root-&gt;{'args'} and $root-&gt;{'args'}-&gt;[1]
              and defined($root-&gt;{'args'}-&gt;[1]-&gt;{'text'})) {
            $value = $self-&gt;protect_text($root-&gt;{'args'}-&gt;[1]-&gt;{'text'});
          }
          push @$attribute, $self-&gt;_arg_line($root);
          return $self-&gt;open_element($command, $attribute)
                         .$value.$self-&gt;close_element($command)."\n";
        } elsif ($root-&gt;{'cmdname'} eq 'clickstyle') {
          my $attribute = [$self-&gt;_arg_line($root)];
          my $value = '';
          if ($root-&gt;{'args'} and $root-&gt;{'args'}-&gt;[0]
              and defined($root-&gt;{'args'}-&gt;[0]-&gt;{'text'})) {
            my $click_command = $root-&gt;{'args'}-&gt;[0]-&gt;{'text'};
            $click_command =~ s/^\@//;
            unshift @$attribute, ('command', $click_command);
            $value = $self-&gt;protect_text($root-&gt;{'args'}-&gt;[0]-&gt;{'text'});
          };
          return $self-&gt;open_element($command, $attribute)
                         .$value.$self-&gt;close_element($command)."\n";
        } else {
          # should only be unmacro
          my $attribute = [$self-&gt;_arg_line($root)];
          if ($root-&gt;{'args'} and $root-&gt;{'args'}-&gt;[0]
              and defined($root-&gt;{'args'}-&gt;[0]-&gt;{'text'})) {
            unshift @$attribute, ('name', $root-&gt;{'args'}-&gt;[0]-&gt;{'text'});
          }
          return $self-&gt;open_element($command, $attribute)
                    .$self-&gt;close_element($command)."\n";
        }
      } elsif ($type eq 'lineraw') {
        if ($root-&gt;{'cmdname'} eq 'c' or $root-&gt;{'cmdname'} eq 'comment') {
          return $self-&gt;format_comment(" $root-&gt;{'cmdname'}".$root-&gt;{'args'}-&gt;[0]-&gt;{'text'})
        } else {
          my $value = '';
          if ($root-&gt;{'args'} and $root-&gt;{'args'}-&gt;[0]
              and defined($root-&gt;{'args'}-&gt;[0]-&gt;{'text'})) {
            $value = $self-&gt;protect_text($root-&gt;{'args'}-&gt;[0]-&gt;{'text'});
          }
          chomp ($value);
          return $self-&gt;open_element($command).$value
                    .$self-&gt;close_element($command)."\n";
        }
      } else {
        print STDERR "BUG: unknown misc_command style $type\n" if ($type !~ /^\d$/);
        my $args_attributes;
        if ($misc_command_numbered_arguments_attributes{$root-&gt;{'cmdname'}}) {
          $args_attributes = $misc_command_numbered_arguments_attributes{$root-&gt;{'cmdname'}};
        } else {
          $args_attributes = ['value'];
        }
        my $attribute = [];
        my $arg_index = 0;
        if (defined($root-&gt;{'extra'}) 
            and defined($root-&gt;{'extra'}-&gt;{'misc_args'})) {
          foreach my $arg_attribute (@{$args_attributes}) {
            if (defined ($root-&gt;{'extra'}-&gt;{'misc_args'}-&gt;[$arg_index])) {
              push @$attribute, ( $arg_attribute, 
                        $root-&gt;{'extra'}-&gt;{'misc_args'}-&gt;[$arg_index]);
            }
            $arg_index++;
          }
        }
        my $end_line;
        if ($root-&gt;{'args'}-&gt;[0]) {
          $end_line = $self-&gt;_end_line_or_comment(
                                         $root-&gt;{'args'}-&gt;[0]-&gt;{'contents'});
          push @$attribute, $self-&gt;_texinfo_line($root-&gt;{'args'}-&gt;[0]);
        } else {
          $end_line = "\n";
        }
        return $self-&gt;open_element($command, $attribute)
                    .$self-&gt;close_element($command).$end_line;
      }
    } elsif ($root-&gt;{'type'}
             and $root-&gt;{'type'} eq 'definfoenclose_command') {
      my $in_monospace_not_normal;
      if (defined($default_args_code_style{$root-&gt;{'cmdname'}})
          and $default_args_code_style{$root-&gt;{'cmdname'}}-&gt;[0]) {
        $in_monospace_not_normal = 1;
      } elsif ($regular_font_style_commands{$root-&gt;{'cmdname'}}) {
        $in_monospace_not_normal = 0;
      }
      push @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}}, 
        $in_monospace_not_normal
          if (defined($in_monospace_not_normal));
      my $arg = $self-&gt;_convert($root-&gt;{'args'}-&gt;[0]);
      $result .= $self-&gt;open_element('infoenclose', ['command', $root-&gt;{'cmdname'},
                                        $self-&gt;_infoenclose_attribute($root)])
                 .$arg.$self-&gt;close_element('infoenclose');
      pop @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}}
        if (defined($in_monospace_not_normal));
    } elsif ($root-&gt;{'args'}
             and exists($Texinfo::Common::brace_commands{$root-&gt;{'cmdname'}})) {
      if ($Texinfo::Common::context_brace_commands{$root-&gt;{'cmdname'}}) {
        push @{$self-&gt;{'document_context'}}, {'monospace' =&gt; [0]};
      }
      if ($Texinfo::Common::inline_format_commands{$root-&gt;{'cmdname'}}
          and $root-&gt;{'extra'} and $root-&gt;{'extra'}-&gt;{'format'}
          and $self-&gt;{'expanded_formats_hash'}-&gt;{$root-&gt;{'extra'}-&gt;{'format'}}) {
        if ($root-&gt;{'cmdname'} eq 'inlineraw') {
          push @{$self-&gt;{'document_context'}}, {'monospace' =&gt; [0]};
          $self-&gt;{'document_context'}-&gt;[-1]-&gt;{'raw'} = 1;
        }
        if (scalar (@{$root-&gt;{'extra'}-&gt;{'brace_command_contents'}}) == 2
            and defined($root-&gt;{'extra'}-&gt;{'brace_command_contents'}-&gt;[-1])) {
          $result .= $self-&gt;_convert({'contents' 
                        =&gt; $root-&gt;{'extra'}-&gt;{'brace_command_contents'}-&gt;[-1]});
        }
        if ($root-&gt;{'cmdname'} eq 'inlineraw') {
          pop @{$self-&gt;{'document_context'}};
        }
        return $result;
      }
      my @elements = @{$commands_elements{$root-&gt;{'cmdname'}}};
      my $command;
      if (scalar(@elements) &gt; 1) {
        $command = shift @elements;
      }
      # this is used for commands without args, or associated to the
      # first argument
      my $attribute = [];
      if ($root-&gt;{'cmdname'} eq 'verb') {
        push @$attribute, ('delimiter', $root-&gt;{'type'});
      } elsif ($root-&gt;{'cmdname'} eq 'anchor') {
        my $anchor_name;
        if (defined($root-&gt;{'extra'}-&gt;{'normalized'})) {
          $anchor_name = $root-&gt;{'extra'}-&gt;{'normalized'};
        } else {
          $anchor_name = '';
        }
        push @$attribute, ('name', $anchor_name);
      }
      my $arg_index = 0;
      foreach my $element (@elements) {
        if (defined($root-&gt;{'args'}-&gt;[$arg_index])) {
          my $in_monospace_not_normal;
          if (defined($default_args_code_style{$root-&gt;{'cmdname'}})
              and $default_args_code_style{$root-&gt;{'cmdname'}}-&gt;[$arg_index]) {
            $in_monospace_not_normal = 1;
          } elsif ($regular_font_style_commands{$root-&gt;{'cmdname'}}) {
            $in_monospace_not_normal = 0;
          }
          push @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}},
            $in_monospace_not_normal
              if (defined($in_monospace_not_normal));
          my $arg = $self-&gt;_convert($root-&gt;{'args'}-&gt;[$arg_index]);
          if ($arg_index &gt; 0) {
            push @$attribute, 
              $self-&gt;_leading_spaces_arg($root-&gt;{'args'}-&gt;[$arg_index]);
          }
          if (!defined($command) or $arg ne '' or scalar(@$attribute) &gt; 0) {
            # ${attribute} is only set for @verb
            push @$attribute, _leading_spaces_before_argument($root)
               if (!defined($command));
            $result .= $self-&gt;open_element($element, $attribute).$arg
                      .$self-&gt;close_element($element);
          }
          $attribute = [];
          pop @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}}
            if (defined($in_monospace_not_normal));
        } else {
          last;
        }
        $arg_index++;
      }
      # This is for the main command
      $attribute = [];
      if ($root-&gt;{'cmdname'} eq 'image') {
        if ($self-&gt;_is_inline($root)) {
          push @$attribute, ('where', 'inline');
        }
      } elsif ($Texinfo::Common::ref_commands{$root-&gt;{'cmdname'}}) {
        if ($root-&gt;{'extra'}-&gt;{'brace_command_contents'}) {
          if ($root-&gt;{'extra'}-&gt;{'node_argument'}
              and $root-&gt;{'extra'}-&gt;{'node_argument'}-&gt;{'node_content'}
              and defined($root-&gt;{'extra'}-&gt;{'node_argument'}-&gt;{'normalized'})) {
            push @$attribute, ('label', 
                 $root-&gt;{'extra'}-&gt;{'node_argument'}-&gt;{'normalized'});
          }
          my $manual;
          my $manual_arg_index = 3;
          if ($root-&gt;{'cmdname'} eq 'inforef') {
            $manual_arg_index = 2;
          }
          if ($root-&gt;{'extra'}-&gt;{'brace_command_contents'}-&gt;[$manual_arg_index]) {
            $manual = Texinfo::Convert::Text::convert({'contents'
             =&gt; $root-&gt;{'extra'}-&gt;{'brace_command_contents'}-&gt;[$manual_arg_index]}, 
                      {'code' =&gt; 1,
                       Texinfo::Common::_convert_text_options($self)});
          }
          if (!defined($manual) and $root-&gt;{'extra'}-&gt;{'node_argument'}
              and $root-&gt;{'extra'}-&gt;{'node_argument'}-&gt;{'manual_content'}) {
            $manual = Texinfo::Convert::Text::convert({'contents' 
                 =&gt; $root-&gt;{'extra'}-&gt;{'node_argument'}-&gt;{'manual_content'}},
              {'code' =&gt; 1, Texinfo::Common::_convert_text_options($self)});
          }
          if (defined($manual)) {
            my $manual_base = $manual;
            $manual_base =~ s/\.[^\.]*$//;
            $manual_base =~ s/^.*\///;
            
            push @$attribute, ('manual', $manual_base)
                  if ($manual_base ne '');
          }
        }
      }
      if (defined($command)) {
        push @$attribute, _leading_spaces_before_argument($root);
        $result = $self-&gt;open_element($command, $attribute).$result
                  .$self-&gt;close_element($command);
      }
      if ($Texinfo::Common::context_brace_commands{$root-&gt;{'cmdname'}}) {
        pop @{$self-&gt;{'document_context'}};
      }
    } elsif (exists($Texinfo::Common::block_commands{$root-&gt;{'cmdname'}})) {
      if ($self-&gt;{'context_block_commands'}-&gt;{$root-&gt;{'cmdname'}}) {
        push @{$self-&gt;{'document_context'}}, {'monospace' =&gt; [0]};
      }
      my $prepended_elements = '';
      my $attribute = [];
      $self-&gt;{'itemize_line'} = 1 if ($root-&gt;{'cmdname'} eq 'itemize');
      if ($root-&gt;{'extra'} and $root-&gt;{'extra'}-&gt;{'command_as_argument'}) {
        my $command_as_arg = $root-&gt;{'extra'}-&gt;{'command_as_argument'};
        push @$attribute,
         ('commandarg', $command_as_arg-&gt;{'cmdname'},
             $self-&gt;_infoenclose_attribute($command_as_arg));
      } elsif ($root-&gt;{'extra'}
               and $root-&gt;{'extra'}-&gt;{'enumerate_specification'}) {
        push @$attribute,('first', $root-&gt;{'extra'}-&gt;{'enumerate_specification'});
      } elsif ($root-&gt;{'cmdname'} eq 'float' and $root-&gt;{'extra'}) {
        if (defined($root-&gt;{'extra'}-&gt;{'normalized'})) {
          push @$attribute, ('name', $root-&gt;{'extra'}-&gt;{'normalized'});
        }
        if ($root-&gt;{'extra'}-&gt;{'type'} and 
            defined($root-&gt;{'extra'}-&gt;{'type'}-&gt;{'normalized'})) {
          push @$attribute, ('type', $root-&gt;{'extra'}-&gt;{'type'}-&gt;{'normalized'});
        }
        if (defined($root-&gt;{'number'})) {
          push @$attribute, ('number', $root-&gt;{'number'});
        }
      } elsif ($root-&gt;{'cmdname'} eq 'verbatim') {
        push @$attribute, ('xml:space', 'preserve');
      } elsif ($root-&gt;{'cmdname'} eq 'macro' 
               or $root-&gt;{'cmdname'} eq 'rmacro') {
        if (defined($root-&gt;{'args'})) {
          my @args = @{$root-&gt;{'args'}};
          my $name_arg = shift @args;
          if (defined($name_arg) and defined($name_arg-&gt;{'text'})) {
            push @$attribute, ('name', $name_arg-&gt;{'text'});
          }
          
          while (@args) {
            my $formal_arg = shift @args;
            $prepended_elements .= $self-&gt;open_element('formalarg')
                .$self-&gt;protect_text($formal_arg-&gt;{'text'})
                .$self-&gt;close_element('formalarg');
          }
        }
        push @$attribute, $self-&gt;_arg_line($root);
      }
      if ($self-&gt;{'expanded_formats_hash'}-&gt;{$root-&gt;{'cmdname'}}) {
        $self-&gt;{'document_context'}-&gt;[-1]-&gt;{'raw'} = 1;
      } else {
        my $end_command = $root-&gt;{'extra'}-&gt;{'end_command'};
        my $end_command_space = [_leading_spaces($end_command)];
        if (scalar(@$end_command_space)) {
          $end_command_space-&gt;[0] = 'endspaces';
        }
        $result .= $self-&gt;open_element($root-&gt;{'cmdname'}, [@$attribute, 
                              _leading_spaces($root), @$end_command_space])
                      .${prepended_elements};
        my $end_line = '';
        if ($root-&gt;{'args'}) {
          if ($commands_args_elements{$root-&gt;{'cmdname'}}) {
            my $arg_index = 0;
            foreach my $element (@{$commands_args_elements{$root-&gt;{'cmdname'}}}) {
              if (defined($root-&gt;{'args'}-&gt;[$arg_index])) {
                my $in_code;
                 $in_code = 1
                  if (defined($default_args_code_style{$root-&gt;{'cmdname'}})
                    and $default_args_code_style{$root-&gt;{'cmdname'}}-&gt;[$arg_index]);
                push @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}}, 1 
                  if ($in_code);
                my $arg;
                if ($arg_index+1 eq scalar(@{$root-&gt;{'args'}})) {
                  # last argument
                  ($arg, $end_line) 
                    = $self-&gt;_convert_argument_and_end_line($root-&gt;{'args'}-&gt;[$arg_index]);
                } else {
                  $arg = $self-&gt;_convert($root-&gt;{'args'}-&gt;[$arg_index]);
                }
                my $spaces = [];
                if ($arg_index != 0) {
                  push @$spaces, $self-&gt;_leading_spaces_arg(
                                              $root-&gt;{'args'}-&gt;[$arg_index]);
                }
                if ($arg ne '' or scalar(@$spaces)) {
                  $result .= $self-&gt;open_element($element, $spaces).$arg
                           .$self-&gt;close_element($element);
                }
                pop @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}} 
                  if ($in_code);
              } else {
                last;
              }
              $arg_index++;
            }
          } else {
            my $contents_possible_comment;
            # in that case the end of line is in the columnfractions line
            # or in the columnprototypes.  
            if ($root-&gt;{'cmdname'} eq 'multitable' and $root-&gt;{'extra'}) {
              if ($root-&gt;{'extra'}-&gt;{'prototypes_line'}) {
                $result .= $self-&gt;open_element('columnprototypes');
                my $first_proto = 1;
                foreach my $prototype (@{$root-&gt;{'extra'}-&gt;{'prototypes_line'}}) {
                  if ($prototype-&gt;{'text'} and $prototype-&gt;{'text'} !~ /\S/) {
                    if (!$first_proto) {
                      my $spaces = $prototype-&gt;{'text'};
                      chomp($spaces);
                      $result .= $spaces;
                    }
                  } else {
                    my $attribute = [];
                    if ($prototype-&gt;{'type'} 
                        and $prototype-&gt;{'type'} eq 'bracketed') {
                      push @$attribute, ('bracketed', 'on');
                      push @$attribute, _leading_spaces_before_argument($prototype);
                    }
                    $result .= $self-&gt;open_element('columnprototype', $attribute)
                           .$self-&gt;_convert($prototype)
                           .$self-&gt;close_element('columnprototype');
                  }
                  $first_proto = 0;
                }
                $result .= $self-&gt;close_element('columnprototypes');
                $contents_possible_comment 
                  = $root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'};
              } elsif ($root-&gt;{'extra'}-&gt;{'columnfractions'}) {
                my $cmd;
                foreach my $content (@{$root-&gt;{'args'}-&gt;[0]-&gt;{'contents'}}) {
                  if ($content-&gt;{'cmdname'}
                      and $content-&gt;{'cmdname'} eq 'columnfractions') {
                    $cmd = $content;
                    last;
                  }
                }
                my $attribute = [$self-&gt;_texinfo_line($cmd-&gt;{'args'}-&gt;[0])];
                $result .= $self-&gt;open_element('columnfractions', $attribute);
                foreach my $fraction (@{$root-&gt;{'extra'}-&gt;{'columnfractions'}}) {
                  $result .= $self-&gt;open_element('columnfraction', 
                                                ['value', $fraction])
                             .$self-&gt;close_element('columnfraction');
                }
                $result .= $self-&gt;close_element('columnfractions');
                $contents_possible_comment 
                  = $root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[-1]-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}
                    if ($root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}
                        and $root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[-1]-&gt;{'args'}
                        and $root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}-&gt;[-1]-&gt;{'args'}-&gt;[-1]-&gt;{'contents'});
              } else { # bogus multitable
                $result .= "\n";
              }
            } else {
              # get end of lines from @*table.
              my $end_spaces = _end_line_spaces($root, 
                                           'space_at_end_block_command');
              if (defined($end_spaces)) {
                $end_line .= $end_spaces 
                # This also catches block @-commands with no argument that
                # have a bogus argument, such as text on @example line
                #print STDERR "NOT xtable: $root-&gt;{'cmdname'}\n" 
                #  if (!$Texinfo::Common::item_line_commands{$root-&gt;{'cmdname'}});
              }
              $contents_possible_comment = $root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'}
                if ($root-&gt;{'args'}-&gt;[-1]-&gt;{'contents'});
            }
            $end_line .= $self-&gt;_end_line_or_comment($contents_possible_comment);
          }
        }
        $result .= $end_line;
        unshift @close_elements, $root-&gt;{'cmdname'};
      }
      delete $self-&gt;{'itemize_line'} if ($self-&gt;{'itemize_line'});
    }
  }
  if ($root-&gt;{'type'}) {
    if (defined($type_elements{$root-&gt;{'type'}})) {
      my $attribute = [];
      if ($root-&gt;{'type'} eq 'preformatted') {
        push @$attribute, ('xml:space', 'preserve');
      } elsif ($root-&gt;{'type'} eq 'menu_entry') {
        push @$attribute, ('leadingtext', $self-&gt;_convert($root-&gt;{'args'}-&gt;[0]));
      } elsif (($root-&gt;{'type'} eq 'menu_entry_node' 
                or $root-&gt;{'type'} eq 'menu_entry_name')
               and $self-&gt;{'pending_menu_entry_separator'}) {
        push @$attribute, ('separator',
               $self-&gt;_convert($self-&gt;{'pending_menu_entry_separator'}));
        delete $self-&gt;{'pending_menu_entry_separator'};
      }
      $result .= $self-&gt;open_element($type_elements{$root-&gt;{'type'}}, $attribute);
    }
    if ($root-&gt;{'type'} eq 'def_line') {
      if ($root-&gt;{'cmdname'}) {
        $result .= $self-&gt;open_element($root-&gt;{'cmdname'}, [_leading_spaces($root)]);
      }
      $result .= $self-&gt;open_element('definitionterm');
      $result .= $self-&gt;_index_entry($root);
      push @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}}, 1;
      if ($root-&gt;{'extra'} and $root-&gt;{'extra'}-&gt;{'def_args'}) {
        my $main_command;
        my $alias;
        if ($Texinfo::Common::def_aliases{$root-&gt;{'extra'}-&gt;{'def_command'}}) {
          $main_command = $Texinfo::Common::def_aliases{$root-&gt;{'extra'}-&gt;{'def_command'}};
          $alias = 1;
        } else {
          $main_command = $root-&gt;{'extra'}-&gt;{'def_command'};
          $alias = 0;
        }
        foreach my $arg (@{$root-&gt;{'extra'}-&gt;{'def_args'}}) {
          my $type = $arg-&gt;[0];
          my $content = $self-&gt;_convert($arg-&gt;[1]);
          if ($type eq 'spaces') {
            $result .= $content;
          } else {
            my $attribute = [];
            if ($type eq 'category' and $alias) {
              push @$attribute, ('automatic', 'on');
            }
            my $element;
            if ($type eq 'name') {
              $element = $defcommand_name_type{$main_command};
            } elsif ($type eq 'arg') {
              $element = 'param';
            } elsif ($type eq 'typearg') {
              $element = 'paramtype';
            } else {
              $element = $type;
            }
            if ($arg-&gt;[1]-&gt;{'type'}
                and $arg-&gt;[1]-&gt;{'type'} eq 'bracketed_def_content') {
              push @$attribute, ('bracketed', 'on');
              push @$attribute, _leading_spaces_before_argument($arg-&gt;[1]);
            }
            $result .= $self-&gt;open_element("def$element", $attribute).$content
                      .$self-&gt;close_element("def$element");
          }
        }
      }
      pop @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}};
      $result .= $self-&gt;close_element('definitionterm');
      if ($root-&gt;{'cmdname'}) {
        $result .= $self-&gt;close_element($root-&gt;{'cmdname'});
      }
      chomp ($result);
      $result .= "\n";
    }
  }
  if ($root-&gt;{'contents'}) {
    my $in_code;
    if ($root-&gt;{'cmdname'} 
        and $Texinfo::Common::preformatted_code_commands{$root-&gt;{'cmdname'}}) {
      $in_code = 1;
    }
    push @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}}, 1 
      if ($in_code);
    if (ref($root-&gt;{'contents'}) ne 'ARRAY') {
      cluck "contents not an array($root-&gt;{'contents'}).";
    }
    foreach my $content (@{$root-&gt;{'contents'}}) {
      $result .= $self-&gt;_convert($content);
    }
    pop @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}}
      if ($in_code);
  }
  my $arg_nr = -1;
  if ($root-&gt;{'type'} and $root-&gt;{'type'} eq 'menu_entry') {
    foreach my $arg (@{$root-&gt;{'args'}}) {
      $arg_nr++;
      # menu_entry_leading_text is added as attribute leadingtext of menu_entry
      # menu_entry_separator is recorded here and then added ass attribute
      # separator
      next if ($arg-&gt;{'type'} eq 'menu_entry_leading_text'
               or $arg-&gt;{'type'} eq 'menu_entry_separator');
      if ($root-&gt;{'args'}-&gt;[$arg_nr +1]
          and $root-&gt;{'args'}-&gt;[$arg_nr +1]-&gt;{'type'}
          and $root-&gt;{'args'}-&gt;[$arg_nr +1]-&gt;{'type'} eq 'menu_entry_separator') {
        $self-&gt;{'pending_menu_entry_separator'} = $root-&gt;{'args'}-&gt;[$arg_nr +1];
      }
      my $in_code;
      if ($arg-&gt;{'type'} eq 'menu_entry_node') {
        $in_code = 1;
      }
      push @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}}, 1 
        if ($in_code);
      $result .= $self-&gt;_convert($arg);
      pop @{$self-&gt;{'document_context'}-&gt;[-1]-&gt;{'monospace'}}
        if ($in_code);
    }
  }
  if ($root-&gt;{'type'}) {
    if (defined($type_elements{$root-&gt;{'type'}})) {
      $result .= $self-&gt;close_element($type_elements{$root-&gt;{'type'}});
    }
  }
  $result = '{'.$result.'}' 
     if ($root-&gt;{'type'} and $root-&gt;{'type'} eq 'bracketed'
         and (!$root-&gt;{'parent'}-&gt;{'type'} or
              ($root-&gt;{'parent'}-&gt;{'type'} ne 'block_line_arg'
               and $root-&gt;{'parent'}-&gt;{'type'} ne 'misc_line_arg')));
  foreach my $element (@close_elements) {
    $result .= $self-&gt;close_element($element);
  }
  if ($root-&gt;{'cmdname'} 
      and exists($Texinfo::Common::block_commands{$root-&gt;{'cmdname'}})) {
    my $end_command = $root-&gt;{'extra'}-&gt;{'end_command'}; 
    if ($self-&gt;{'expanded_formats_hash'}-&gt;{$root-&gt;{'cmdname'}}) {
    } else {
      my $end_line = '';
      if ($end_command) {
        my $end_spaces = _end_line_spaces($end_command, 'spaces_at_end');
        $end_line .= $end_spaces if (defined($end_spaces));
        $end_line 
         .= $self-&gt;_end_line_or_comment($end_command-&gt;{'args'}-&gt;[0]-&gt;{'contents'})
           if ($end_command-&gt;{'args'}-&gt;[0]
               and $end_command-&gt;{'args'}-&gt;[0]-&gt;{'contents'});
      } else {
        #$end_line = "\n";
      }
      $result .= $end_line;
    }
    if ($self-&gt;{'context_block_commands'}-&gt;{$root-&gt;{'cmdname'}}) {
      pop @{$self-&gt;{'document_context'}};
    }
  # The command is closed either when the corresponding tree element
  # is done, and the command is not associated to an element, or when
  # the element is closed.
  } elsif ((($root-&gt;{'type'} and $root-&gt;{'type'} eq 'element'
             and $root-&gt;{'extra'} and $root-&gt;{'extra'}-&gt;{'element_command'}
             and !($root-&gt;{'extra'}-&gt;{'element_command'}-&gt;{'cmdname'}
                   and $root-&gt;{'extra'}-&gt;{'element_command'}-&gt;{'cmdname'} eq 'node'))
            or ($root-&gt;{'cmdname'} 
                and $Texinfo::Common::root_commands{$root-&gt;{'cmdname'}}
                and $root-&gt;{'cmdname'} ne 'node'
                and !($root-&gt;{'parent'} and $root-&gt;{'parent'}-&gt;{'type'}
                     and $root-&gt;{'parent'}-&gt;{'type'} eq 'element'
                     and $root-&gt;{'parent'}-&gt;{'extra'} 
                     and $root-&gt;{'parent'}-&gt;{'extra'}-&gt;{'element_command'}
                     and $root-&gt;{'parent'}-&gt;{'extra'}-&gt;{'element_command'} eq $root)))
           and !$self-&gt;get_conf('USE_NODES')) {
    if ($root-&gt;{'type'} and $root-&gt;{'type'} eq 'element') {
      $root = $root-&gt;{'extra'}-&gt;{'element_command'};
    }
    my $command = $self-&gt;_level_corrected_section($root);
    if (!($root-&gt;{'section_childs'} and scalar(@{$root-&gt;{'section_childs'}}))
        or $command eq 'top') {
      $result .= $self-&gt;close_element($command)."\n";
      my $current = $root;
      while ($current-&gt;{'section_up'}
             # the most up element is a virtual sectioning root element, this
             # condition avoids getting into it
             and $current-&gt;{'section_up'}-&gt;{'cmdname'}
             and !$current-&gt;{'section_next'}
             and $self-&gt;_level_corrected_section($current-&gt;{'section_up'}) ne 'top') {
        $current = $current-&gt;{'section_up'};
        $result .= $self-&gt;close_element($self-&gt;_level_corrected_section($current)) ."\n";
      }
    }
    if ($self-&gt;{'pending_bye'}) {
      $result .= $self-&gt;{'pending_bye'};
      delete $self-&gt;{'pending_bye'};
    }
  } elsif ((($root-&gt;{'type'} and $root-&gt;{'type'} eq 'element'
             and $root-&gt;{'extra'} and $root-&gt;{'extra'}-&gt;{'element_command'}
             and $root-&gt;{'extra'}-&gt;{'element_command'}-&gt;{'cmdname'}
             and $root-&gt;{'extra'}-&gt;{'element_command'}-&gt;{'cmdname'} eq 'node')
            or ($root-&gt;{'cmdname'} 
                and $root-&gt;{'cmdname'} eq 'node'
                and !($root-&gt;{'parent'} and $root-&gt;{'parent'}-&gt;{'type'}
                     and $root-&gt;{'parent'}-&gt;{'type'} eq 'element'
                     and $root-&gt;{'parent'}-&gt;{'extra'} 
                     and $root-&gt;{'parent'}-&gt;{'extra'}-&gt;{'element_command'}
                     and $root-&gt;{'parent'}-&gt;{'extra'}-&gt;{'element_command'} eq $root)))
           and $self-&gt;get_conf('USE_NODES')) {
    #if ($root-&gt;{'type'} and $root-&gt;{'type'} eq 'element') {
    #  $root = $root-&gt;{'extra'}-&gt;{'element_command'};
    #}
    $result .= $self-&gt;close_element('node');
    
    if ($self-&gt;{'pending_bye'}) {
      $result .= $self-&gt;{'pending_bye'};
      delete $self-&gt;{'pending_bye'};
    }
  }
  return $result;
}

1;

__END__
# Automatically generated from maintain/template.pod

=head1 NAME

Texinfo::Convert::TexinfoXML - Convert Texinfo tree to TexinfoXML

=head1 SYNOPSIS

  my $converter 
    = Texinfo::Convert::TexinfoXML-&gt;converter({'parser' =&gt; $parser});

  $converter-&gt;output($tree);

=head1 DESCRIPTION

Texinfo::Convert::TexinfoXML converts a Texinfo tree to TexinfoXML.

=head1 METHODS

=over

=item $converter = Texinfo::Convert::TexinfoXML-&gt;converter($options)

Initialize an TexinfoXML converter.  

The I&lt;$options&gt; hash reference holds options for the converter.  In
this option hash reference a parser object may be associated with the 
I&lt;parser&gt; key.  The other options should be configuration options
described in the Texinfo manual.  Those options, when appropriate,
override the document content.

See L&lt;Texinfo::Convert::Converter&gt; for more informations.

=item $converter-&gt;output($tree)

Convert a Texinfo tree I&lt;$tree&gt; and output the result in files as
described in the Texinfo manual.

=item $result = $converter-&gt;convert($tree)

Convert a Texinfo tree I&lt;$tree&gt; or tree portion and return 
the resulting output.

=item $result = $converter-&gt;convert_tree($tree)

Convert a Texinfo tree portion I&lt;$tree&gt; and return the resulting 
output.  This function do not try to output a full document but only
portions of document.  For a full document use C&lt;convert&gt;.

=item $result = $converter-&gt;output_internal_links()

Returns text representing the links in the document.  At present the format 
should follow the C&lt;--internal-links&gt; option of texi2any/makeinfo specification
and this is only relevant for HTML.

=back

=head1 AUTHOR

Patrice Dumas, E&lt;lt&gt;pertusus@free.frE&lt;gt&gt;

=head1 COPYRIGHT AND LICENSE

Copyright 2012 Free Software Foundation, Inc.

This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or (at 
your option) any later version.

=cut
</pre></body></html>