⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch03_08.htm

📁 Perl & XML. by Erik T. Ray and Jason McIntosh ISBN 0-596-00205-X First Edition, published April
💻 HTM
字号:
<html><head><title>XML::Writer (Perl and XML)</title><link rel="stylesheet" type="text/css" href="../style/style1.css" /><meta name="DC.Creator" content="Erik T. Ray and Jason McIntosh" /><meta name="DC.Format" content="text/xml" scheme="MIME" /><meta name="DC.Language" content="en-US" /><meta name="DC.Publisher" content="O'Reilly &amp; Associates, Inc." /><meta name="DC.Source" scheme="ISBN" content="059600205XL" /><meta name="DC.Subject.Keyword" content="stuff" /><meta name="DC.Title" content="Perl and XML" /><meta name="DC.Type" content="Text.Monograph" /></head><body bgcolor="#ffffff"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl &amp; XML" /><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><table width="684" border="0"><tr><td align="left" valign="top" width="228"><a href="ch03_07.htm"><img alt="Previous" border="0" src="../gifs/txtpreva.gif" /></a></td><td align="center" valign="top" width="228" /><td align="right" valign="top" width="228"><a href="ch03_09.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr></table></div><h2 class="sect1">3.8. XML::Writer</h2><p>Compared<a name="INDEX-276" /> to all we've had todeal with in this chapter so far, writing XML will be a breeze.It's easier to write it because now theshoe's on the other foot: your program has a datastructure over which it has had complete control and knows everythingabout, so it doesn't need to prepare for everycontingency that it might encounter when processing input.</p><p>There's nothing particularly difficult aboutgenerating XML. You know about elements with start and end tags,their attributes, and so on. It's just tedious towrite an XML output method that remembers to cross all thet's and dot all the i's. Does itput a space between every attribute? Does it close open elements?Does it put that slash at the end of empty elements? Youdon't want to have to think about these things whenyou're writing more important code. Others havewritten modules to take care of these serialization details for you.</p><p>David Megginson's <tt class="literal">XML::Writer</tt> isa fine example of an abstract XML generation interface. It comes witha handful of very simple methods for building any XML document. Justcreate a writer object and call its methods to crank out a stream ofXML. <a href="ch03_08.htm#perlxml-CHP-3-TABLE-1">Table 3-1</a> lists some of these<a name="INDEX-277" />methods.</p><a name="perlxml-CHP-3-TABLE-1" /><h4 class="objtitle">Table 3-1. XML::Writer methods </h4><table border="1"><tr><th><p>Name</p></th><th><p>Function</p></th></tr><tr><td><p><tt class="literal">end( )</tt><a name="INDEX-278" /></p></td><td><p>Close the document and perform simple well-formedness checking (e.g.,make sure that there is one root element and that every start tag hasan associated end tag). If the option <tt class="literal">UNSAFE</tt> isset, however, most well-formedness checking is skipped.</p></td></tr><tr><td><p><tt class="literal">xmlDecl([$endoding,$standalone])</tt><a name="INDEX-279" /></p></td><td><p>Add an XML Declaration at the top of the document. The version ishard-wired as "1.0".</p></td></tr><tr><td><p><tt class="literal">doctype($name, [$publicId,$systemId])</tt><a name="INDEX-280" /></p></td><td><p>Add a document type declaration at the top of the document. </p></td></tr><tr><td><p><tt class="literal">comment($text)</tt><a name="INDEX-281" /></p></td><td><p>Write an XML comment. </p></td></tr><tr><td><p><tt class="literal">pi($target [, $data])</tt><a name="INDEX-282" /></p></td><td><p>Output a processing instruction. </p></td></tr><tr><td><p><tt class="literal">startTag($name [, $aname1 =&gt; $value1,...])</tt><a name="INDEX-283" /></p></td><td><p>Create an element start tag. The first argument is the element name,which is followed by attribute name-value pairs.</p></td></tr><tr><td><p><tt class="literal">emptyTag($name [, $aname1 =&gt; $value1,...])</tt><a name="INDEX-284" /></p></td><td><p>Set up an empty element tag. The arguments are the same as for the<tt class="literal">startTag( )</tt> method.</p></td></tr><tr><td><p><tt class="literal">endTag([$name])</tt><a name="INDEX-285" /></p></td><td><p>Create an element end tag. Leave out the argument to have it closethe currently open element automatically.</p></td></tr><tr><td><p><tt class="literal">dataElement($name, $data [, $aname1 =&gt; $value1,...])</tt><a name="INDEX-286" /></p></td><td><p>Print an element that contains only character data. This elementincludes the start tag, the data, and the end tag.</p></td></tr><tr><td><p><tt class="literal">characters($data)</tt><a name="INDEX-287" /></p></td><td><p>Output a parcel of character data. </p></td></tr></table><p><p>Using these routines, we can build a complete XML document. Theprogram in <a href="ch03_08.htm#perlxml-CHP-3-EX-10">Example 3-10</a>, for example, creates a basicHTML file.</p><a name="perlxml-CHP-3-EX-10" /><div class="example"><h4 class="objtitle">Example 3-10. HTML generator </h4><blockquote><pre class="code">use IO;my $output = new IO::File("&gt;output.xml");use XML::Writer;my $writer = new XML::Writer( OUTPUT =&gt; $output );$writer-&gt;xmlDecl( 'UTF-8' );$writer-&gt;doctype( 'html' );$writer-&gt;comment( 'My happy little HTML page' );$writer-&gt;pi( 'foo', 'bar' );$writer-&gt;startTag( 'html' );$writer-&gt;startTag( 'body' );$writer-&gt;startTag( 'h1' );$writer-&gt;startTag( 'font', 'color' =&gt; 'green' );$writer-&gt;characters( "&lt;Hello World!&gt;" );$writer-&gt;endTag( );$writer-&gt;endTag( );$writer-&gt;dataElement( "p", "Nice to see you." );$writer-&gt;endTag( );$writer-&gt;endTag( );$writer-&gt;end( );</pre></blockquote></div><p>This example outputs the following: </p><blockquote><pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;!DOCTYPE html&gt;&lt;!-- My happy little HTML page --&gt;&lt;?foo bar?&gt;&lt;html&gt;&lt;body&gt;&lt;h1&gt;&lt;font color="green"&gt;&amp;lt;Hello World!&amp;gt;&lt;/font&gt;&lt;/h1&gt;&lt;p&gt;Nice to see you.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</pre></blockquote><p>Some nice conveniences are built into this module. For example, itautomatically takes care of illegal characters likethe<a name="INDEX-288" /><a name="INDEX-289" />ampersand (<tt class="literal">&amp;</tt>) by turning them into theappropriate entity references. Quoting of entity values is automatic,too. At any time during the document-building process, you can checkthe context you're in with predicate methods like<tt class="literal">within_element('foo')</tt>, which tells you if anelement named <tt class="literal">'foo'</tt> is open.</p><p>By default, the module outputs a document with all the tags runtogether. You might prefer to insert whitespace in some places tomake the XML more readable. If you set the option<tt class="literal">NEWLINES</tt> to true, then it will insert newlinecharacters after element tags. If you set<tt class="literal">DATA_MODE</tt>, a similar effect will be achieved, andyou can combine <tt class="literal">DATA_MODE</tt> with<tt class="literal">DATA_INDENT</tt> to automatically indent lines inproportion to depth in the document for a nicely formatted document.</p><p>The nice thing about XML is that it can be used to organize justabout any kind of textual data. With <tt class="literal">XML::Writer</tt>,you can quickly turn a pile of information into a tightly regimenteddocument. For example, you can turn a directory listing into ahierarchical database like the program in <a href="ch03_08.htm#perlxml-CHP-3-EX-11">Example 3-11</a>. </p><a name="perlxml-CHP-3-EX-11" /><div class="example"><h4 class="objtitle">Example 3-11. Directory mapper </h4><blockquote><pre class="code">use XML::Writer;my $wr = new XML::Writer( DATA_MODE =&gt; 'true', DATA_INDENT =&gt; 2 );&amp;as_xml( shift @ARGV );$wr-&gt;end;# recursively map directory information into XML#sub as_xml {    my $path = shift;    return unless( -e $path );    # if this is a directory, create an element and    # stuff it full of items    if( -d $path ) {        $wr-&gt;startTag( 'directory', name =&gt; $path );        # Load the names of all things in this        # directory into an array        my @contents = ( );        opendir( DIR, $path );        while( my $item = readdir( DIR )) {            next if( $item eq '.' or $item eq '..' );            push( @contents, $item );        }        closedir( DIR );        # recurse on items in the directory        foreach my $item ( @contents ) {            &amp;as_xml( "$path/$item" );        }        $wr-&gt;endTag( 'directory' );    # We'll lazily call anything that's not a directory a file.    } else {        $wr-&gt;emptyTag( 'file', name =&gt; $path );    }}</pre></blockquote></div><p>Here's how the example looks when run on a directory(note the use of <tt class="literal">DATA_MODE</tt> and<tt class="literal">DATA_INDENT</tt> to improve readability):</p><blockquote><pre class="code">$ <tt class="userinput"><b>~/bin/dir /home/eray/xtools/XML-DOM-1.25</b></tt>&lt;directory name="/home/eray/xtools/XML-DOM-1.25"&gt;  &lt;directory name="/home/eray/xtools/XML-DOM-1.25/t"&gt;    &lt;file name="/home/eray/xtools/XML-DOM-1.25/t/attr.t" /&gt;    &lt;file name="/home/eray/xtools/XML-DOM-1.25/t/minus.t" /&gt;    &lt;file name="/home/eray/xtools/XML-DOM-1.25/t/example.t" /&gt;    &lt;file name="/home/eray/xtools/XML-DOM-1.25/t/print.t" /&gt;    &lt;file name="/home/eray/xtools/XML-DOM-1.25/t/cdata.t" /&gt;    &lt;file name="/home/eray/xtools/XML-DOM-1.25/t/astress.t" /&gt;    &lt;file name="/home/eray/xtools/XML-DOM-1.25/t/modify.t" /&gt;  &lt;/directory&gt;  &lt;file name="/home/eray/xtools/XML-DOM-1.25/DOM.gif" /&gt;  &lt;directory name="/home/eray/xtools/XML-DOM-1.25/samples"&gt;    &lt;file    name="/home/eray/xtools/XML-DOM-1.25/samples/REC-xml-19980210.xml"    /&gt;  &lt;/directory&gt;  &lt;file name="/home/eray/xtools/XML-DOM-1.25/MANIFEST" /&gt;  &lt;file name="/home/eray/xtools/XML-DOM-1.25/Makefile.PL" /&gt;  &lt;file name="/home/eray/xtools/XML-DOM-1.25/Changes" /&gt;  &lt;file name="/home/eray/xtools/XML-DOM-1.25/CheckAncestors.pm" /&gt;  &lt;file name="/home/eray/xtools/XML-DOM-1.25/CmpDOM.pm" /&gt;</pre></blockquote><p>We've seen <tt class="literal">XML::Writer</tt> used stepby step and in a recursive context. You could also use itconveniently inside an object tree structure, where each XML objecttype has its own "to-string" methodmaking the appropriate calls to the writer object.<tt class="literal">XML::Writer</tt> is extremely flexible and useful.</p><a name="perlxml-CHP-3-SECT-8.1" /><div class="sect2"><h3 class="sect2">3.8.1. Other Methods of Output</h3><p>Remember that many parser modules have their own ways to turn theircurrent content into simple, pretty strings of XML.<tt class="literal">XML::LibXML</tt>, for example, lets you call a<tt class="literal">toString( )</tt><a name="INDEX-290" /> method on the document or any elementobject within it. Consequently, more specific processor classes thatsubclass from this module or otherwise make internal use of it oftenmake the same method available in their own APIs and pass end usercalls to it to the underlying parser object. Consult thedocumentation of your favorite processor to see if it supports thisor a similar feature.</p><p>Finally, sometimes all you really need is Perl's<tt class="literal">print</tt> function. While it lives at a lower levelthan tools like <tt class="literal">XML::Writer</tt>, ignorant ofXML-specific rules and regulations, it gives you a finer degree ofcontrol over the process of turning memory structures into textworthy of throwing at filehandles. If you're doingespecially tricky work, falling back to <tt class="literal">print</tt> maybe a relief, and indeed some of the stunts we pull in <a href="ch10_01.htm">Chapter 10, "Coding Strategies"</a> use <tt class="literal">print</tt>. Justdon't forget to escape those naughty<tt class="literal">&lt;</tt> and <tt class="literal">&amp;</tt> characters withtheir respective entity references, as shown in <a href="ch02_05.htm#perlxml-CHP-2-TABLE-1">Table 2-1</a>, or be generous with CDATA sections.<a name="INDEX-291" /></p></div><hr width="684" align="left" /><div class="navbar"><table width="684" border="0"><tr><td align="left" valign="top" width="228"><a href="ch03_07.htm"><img alt="Previous" border="0" src="../gifs/txtpreva.gif" /></a></td><td align="center" valign="top" width="228"><a href="index.htm"><img alt="Home" border="0" src="../gifs/txthome.gif" /></a></td><td align="right" valign="top" width="228"><a href="ch03_09.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr><tr><td align="left" valign="top" width="228">3.7. Document Validation</td><td align="center" valign="top" width="228"><a href="index/index.htm"><img alt="Book Index" border="0" src="../gifs/index.gif" /></a></td><td align="right" valign="top" width="228">3.9. Character Sets and Encodings</td></tr></table></div><hr width="684" align="left" /><img alt="Library Navigation Links" border="0" src="../gifs/navbar.gif" usemap="#library-map" /><p><p><font size="-1"><a href="copyrght.htm">Copyright &copy; 2002</a> O'Reilly &amp; Associates. All rights reserved.</font></p><map name="library-map"><area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -