XML-Writer

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

        - Permitted in-document namespace prefix control
        - Don't reopen STDOUT for output (closes #6232)
        - Moved tests into t/. Added tests for mid-document namespace changes.
          Show diffs when comparison tests fail

0.500 Sat Mar  6 22:45:54 GMT 2004    <joe@kafsemo.org>
        - Prepared metadata for a consistent, CPAN-friendly 0.500 release
        - Added a META.yml to prevent XML::Writer::Namespaces from
          being indexed
        - Writer.pm: Removed a duplicate check for valid attribute names
        - test.pl: Added more tests for full coverage of the cdata method

0.4.6 Tue Mar  2 16:54:04 GMT 2004    <joe@kafsemo.org>
        - test.pl: Revert to using a temporary file, rather than an
          IO::String, for compatibility with older Perls

0.4.5 Mon Mar  1 14:46:47 GMT 2004    <joe@kafsemo.org>
        - added FORCED_NS_DECLS parameter, to declare namespaces ahead of use
        - fixed check for duplicate attributes
        - correctly take the default namespace from the supplied prefix map
        - no longer produce namespace declarations for the 'xml:' prefix
        - allow xml-stylesheet PIs
        - fixed warnings about uninitialised values
        - added a comprehensive suite of tests, using Test::More

0.4.2 Sun Feb 22 15:33:44 GMT 2004    ed@membled.com
        - added raw() to print raw, unescaped text
        - patch from srinithan adding cdata() and cdataElement() to
          write CDATA sections

0.4.1 Sat Oct 18 19:51:51 BST 2003    ed@membled.com
        - fixed deprecation warning from 'use IO'

0.4 Tue Apr  4 21:59:51 EDT 2000
        - added support for a simple data mode (off by default), with
          no mixed content and automatic whitespace and indenting
        - added get/setDataMode and get/setDataIndent methods
        - added DATA_MODE and DATA_INDENT parameters to constructor

Writer.pm  view on Meta::CPAN

    $output->print($_[0]);
    # Don't set $hasData or any other information: we know nothing
    # about what was just written.
    #
  };

  my $SAFE_raw = sub {
    croak('raw() is only available when UNSAFE is set');
  };

  my $cdata = sub {
      my $data = $_[0];
      $data    =~ s/\]\]>/\]\]\]\]><!\[CDATA\[>/g;
      $output->print("<![CDATA[$data]]>");
      $hasData = 1;
  };

  my $SAFE_cdata = sub {
    if ($elementLevel < 1) {
      croak("Attempt to insert characters outside of document element");
    } elsif ($dataMode && $hasElement) {
      croak("Mixed content not allowed in data mode: characters");
    } else {
      _croakUnlessDefinedCharacters($_[0]);
      &{$checkUnencodedRepertoire}($_[0]);
      &{$cdata};
    }
  };

                                # Assign the correct closures based on
                                # the UNSAFE parameter
  if ($unsafe) {
    $self = {'END' => $end,
             'XMLDECL' => $xmlDecl,
             'PI' => $pi,
             'COMMENT' => $comment,
             'DOCTYPE' => $doctype,
             'STARTTAG' => $startTag,
             'EMPTYTAG' => $emptyTag,
             'ENDTAG' => $endTag,
             'CHARACTERS' => $characters,
             'RAW' => $raw,
             'CDATA' => $cdata
            };
  } else {
    $self = {'END' => $SAFE_end,
             'XMLDECL' => $SAFE_xmlDecl,
             'PI' => $SAFE_pi,
             'COMMENT' => $SAFE_comment,
             'DOCTYPE' => $SAFE_doctype,
             'STARTTAG' => $SAFE_startTag,
             'EMPTYTAG' => $SAFE_emptyTag,
             'ENDTAG' => $SAFE_endTag,
             'CHARACTERS' => $SAFE_characters,
             'RAW' => $SAFE_raw,               # This will intentionally fail
             'CDATA' => $SAFE_cdata
            };
  }

                                # Query methods
  $self->{'IN_ELEMENT'} = sub {
    my ($ancestor) = (@_);
    return $elementStack[$#elementStack] eq $ancestor;
  };

  $self->{'WITHIN_ELEMENT'} = sub {

Writer.pm  view on Meta::CPAN

sub dataElement {
  my ($self, $name, $data, @atts) = (@_);
  $self->startTag($name, @atts);
  $self->characters($data);
  $self->endTag($name);
}

#
# Write a simple CDATA element.
#
sub cdataElement {
    my ($self, $name, $data, %atts) = (@_);
    $self->startTag($name, %atts);
    $self->cdata($data);
    $self->endTag($name);
}

#
# Write character data.
#
sub characters {
  my $self = shift;
  &{$self->{CHARACTERS}};
}

Writer.pm  view on Meta::CPAN

# Write raw, unquoted, completely unchecked character data.
#
sub raw {
  my $self = shift;
  &{$self->{RAW}};
}

#
# Write CDATA.
#
sub cdata {
    my $self = shift;
    &{$self->{CDATA}};
}

#
# Query the current element.
#
sub in_element {
  my $self = shift;
  return &{$self->{IN_ELEMENT}};

Writer.pm  view on Meta::CPAN


Print data completely unquoted and unchecked to the XML document.  For
example C<raw('<')> will print a literal < character.  This
necessarily bypasses all well-formedness checking, and is therefore
only available in unsafe mode.

This can sometimes be useful for printing entities which are defined
for your XML format but the module doesn't know about, for example
&nbsp; for XHTML.

=item cdata($data)

As C<characters()> but writes the data quoted in a CDATA section, that
is, between <![CDATA[ and ]]>.  If the data to be written itself
contains ]]>, it will be written as several consecutive CDATA
sections.

=item cdataElement($name, $data [, $aname1 => $value1, ...])

As C<dataElement()> but the element content is written as one or more
CDATA sections (see C<cdata()>).

=item setOutput($output)

Set the current output destination, as in the OUTPUT parameter for the
constructor.

=item getOutput()

Return the current output destination, as in the OUTPUT parameter for
the constructor.

t/01_main.t  view on Meta::CPAN

	$w->startTag("foo");
	expectError('raw\(\) is only available when UNSAFE is set', eval {
		$w->raw("<bar/>");
	});
}

# Inserting a CDATA section.
TEST: {
	initEnv();
	$w->startTag("foo");
	$w->cdata("cdata testing - test");
	$w->endTag("foo");
	$w->end();
	checkResult("<foo><![CDATA[cdata testing - test]]></foo>\n",
		'cdata() should create CDATA sections');
};

# Inserting CDATA containing CDATA delimeters ']]>'.
TEST: {
	initEnv();
	$w->startTag("foo");
	$w->cdata("This is a CDATA section <![CDATA[text]]>");
	$w->endTag("foo");
	$w->end();
	checkResult("<foo><![CDATA[This is a CDATA section <![CDATA[text]]]]><![CDATA[>]]></foo>\n", 'If a CDATA section would be invalid, it should be split up');
};

# cdataElement().
TEST: {
	initEnv();
	$w->cdataElement("foo", "hello", a => 'b');
	$w->end();
	checkResult(qq'<foo a="b"><![CDATA[hello]]></foo>\n',
		'cdataElement should produce a valid element containing a CDATA section');
};

# Verify that writing characters using CDATA outside of an element fails
TEST: {
	initEnv();
	expectError('Attempt to insert characters outside of document element',
		eval {
			$w->cdata('Test');
		});
};

# Expect to break on mixed content in data mode
TEST: {
	initEnv();
	$w->setDataMode(1);
	$w->startTag('x');
	$w->cdata('Text');
	expectError("Mixed content not allowed in data mode: element x", eval {
		$w->startTag('x');
	});
};

# Break with mixed content when the element is written before the characters
TEST: {
	initEnv();
	$w->setDataMode(1);
	$w->startTag('x');
	$w->emptyTag('empty');
	expectError("Mixed content not allowed in data mode: characters", eval {
		$w->cdata('Text');
	});
};

# Make sure addPrefix-caused clashes are resolved
TEST: {
	initEnv();

	$w->addPrefix('a', '');
	$w->addPrefix('b', '');

t/01_main.t  view on Meta::CPAN

	is($w->getOutput(), \*STDOUT, 'If no output is given, STDOUT should be used');
};

# Create an ill-formed document using unsafe mode
TEST: {
	initEnv(UNSAFE => 1);

	$w->xmlDecl('us-ascii');
	$w->comment("--");
	$w->characters("Test\n");
	$w->cdata("Test\n");
	$w->doctype('y', undef, '/');
	$w->emptyTag('x');
	$w->end();
	checkResult(<<EOR, 'Unsafe mode should not enforce validity tests.');
<?xml version="1.0" encoding="us-ascii"?>
<!-- -- -->
Test
<![CDATA[Test
]]><!DOCTYPE y SYSTEM "/">
<x />

t/01_main.t  view on Meta::CPAN

	$w->dataElement('b', '$');

	# I need U+00A3 as an is_utf8 string; I want to keep the source ASCII.
	# There must be a better way to do this.
	require Encode;
	my $text = Encode::decode('iso-8859-1', "\x{A3}");
	$w->dataElement('b', $text);

	$w->dataElement('b', "\x{20AC}");
	$w->startTag('c');
	$w->cdata(" \$ \x{A3} \x{20AC} ");
	$w->endTag('c');
	$w->endTag('a');
	$w->end();

	checkResult(<<EOR, 'When requested, output should be UTF-8 encoded');
<?xml version="1.0" encoding="utf-8"?>
<!-- \$ \x{C2}\x{A3} \x{E2}\x{82}\x{AC} -->

<a>
<b>\x{24}</b>

t/01_main.t  view on Meta::CPAN

	# Make sure non-ASCII characters that can't be represented
	#  as references cause failure

	# I need U+00A3 as an is_utf8 string; I want to keep the source ASCII.
	# There must be a better way to do this.
	require Encode;
	my $text = Encode::decode('iso-8859-1', "\x{A3}");

	initEnv(ENCODING => 'us-ascii', DATA_MODE => 1);
	$w->startTag('a');
	$w->cdata('Text');
	expectError('ASCII', eval {
		$w->cdata($text);
	});


	initEnv(ENCODING => 'us-ascii', DATA_MODE => 1);
	$w->startTag('a');
	$w->comment('Text');
	expectError('ASCII', eval {
		$w->comment($text);
	});

t/01_main.t  view on Meta::CPAN

	initEnv(ENCODING => 'us-ascii', DATA_MODE => 1);
	expectError("Non-ASCII characters are not permitted in this part of ", eval {
		$w->emptyTag("foo", "fianc\x{E9}" => 'true');
	});


	# Make sure Unicode generates warnings when it makes it through
	#  to a US-ASCII-encoded stream
	initEnv(ENCODING => 'us-ascii', DATA_MODE => 1, UNSAFE => 1);
	$w->startTag('a');
	$w->cdata($text);
	$w->endTag('a');
	$w->end();

	$outputFile->flush();
	ok($warning && $warning =~ /does not map to ascii/,
		'Perl IO should warn about non-ASCII characters in output');
	

	initEnv(ENCODING => 'us-ascii', DATA_MODE => 1, UNSAFE => 1);
	$w->startTag('a');

t/01_main.t  view on Meta::CPAN

	checkResult(<<"EOR", 'Whitespace below \u0020 is valid.');
<x>\x09\x0A\x0D </x>
EOR


	# CDATA

	initEnv();
	$w->startTag('x');
	expectError('\u0000', eval {
		$w->cdata("\x00");
	});

	initEnv();

	$w->startTag('x');
	$w->cdata("\x09\x0A\x0D ");
	$w->endTag('x');
	$w->end();

	checkResult(<<"EOR", 'Whitespace below \u0020 is valid.');
<x><![CDATA[\x09\x0A\x0D ]]></x>
EOR


	# Attribute values

t/01_main.t  view on Meta::CPAN

	initEnv(UNSAFE => 1);

	$w->dataElement('x', "\x00");
	$w->end();
	checkResult(<<"EOR", 'Unsafe mode should not enforce character validity tests');
<x>\x00</x>
EOR

	initEnv(UNSAFE => 1);
	$w->startTag('x');
	$w->cdata("\x00");
	$w->endTag('x');
	$w->end();
	checkResult(<<"EOR", 'Unsafe mode should not enforce character validity tests');
<x><![CDATA[\x00]]></x>
EOR

	initEnv(UNSAFE => 1);
	$w->emptyTag('x', 'a' => "\x00");
	$w->end();
	checkResult(<<"EOR", 'Unsafe mode should not enforce character validity tests');



( run in 0.240 second using v1.01-cache-2.11-cpan-ec4f86ec37b )