<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://microformats.org/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=1143297912</id>
	<title>Microformats Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://microformats.org/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=1143297912"/>
	<link rel="alternate" type="text/html" href="https://microformats.org/wiki/Special:Contributions/1143297912"/>
	<updated>2026-04-15T01:45:51Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.38.4</generator>
	<entry>
		<id>https://microformats.org/wiki/index.php?title=hlisting&amp;diff=5566</id>
		<title>hlisting</title>
		<link rel="alternate" type="text/html" href="https://microformats.org/wiki/index.php?title=hlisting&amp;diff=5566"/>
		<updated>2006-03-25T14:42:15Z</updated>

		<summary type="html">&lt;p&gt;1143297912: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=hListing Proposal=&lt;br /&gt;
&lt;br /&gt;
hListing is a proposal for an open, distributed listings format suitable for embedding in (X)HTML, Atom, RSS, and arbitrary XML. hListing would be one of several [[microformats]] open standards.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Draft Proposal 2006-02-07 ==&lt;br /&gt;
&lt;br /&gt;
===Editor===&lt;br /&gt;
* Rohit Khare, [http://commerce.net/ CommerceNet]&lt;br /&gt;
&lt;br /&gt;
===Authors===&lt;br /&gt;
* Assaf Arkin, [http://blog.labnotes.org/ Labnotes]&lt;br /&gt;
* Craig Donato, [http://oodle.com/ Oodle]&lt;br /&gt;
* Rohit Khare, [http://commerce.net/ CommerceNet]&lt;br /&gt;
&lt;br /&gt;
===Contributors===&lt;br /&gt;
* Tantek Çelik&lt;br /&gt;
* Ryan King&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
Individuals and professionals are increasingly publishing their offerings online: whether as items for sale or rent (cars, homes, apartments), services for hire (music lessons, dog walker, plumber), openings (jobs, volunteers, extra spot in a book club) or personals (people looking for dates, companions, roommates).  The goal of publishing (and promoting) these listings online is to seek out interested parties, often within a limited time period.&lt;br /&gt;
&lt;br /&gt;
While descriptions of products and services are common on the Web, particularly on e-commerce sites, we are proposing an hListing microformat for sharing, searching, and syndicating the information that helps match up buyers and sellers. This proposal follows the common practices of trading sites such as Craigslist, eBay and newspaper classifieds.&lt;br /&gt;
&lt;br /&gt;
If [[hreview|hReview]] is about an item and what you think of it, hListing is about an item and what you want to ''do'' with it.&lt;br /&gt;
&lt;br /&gt;
=== Inspiration and Acknowledgments ===&lt;br /&gt;
Thanks to everyone who participated in the initial burst of hListing activity in August 2005, particularly Emiliano Martínez Luque and Trevor O'Reilly, for naming the effort and organizing the listing-{brainstorming, formats, examples} pages on the wiki. We would like to thank Tantek for an initial debate about whether to extend hReview or pursue an independent-though-similar hListing for our proposal.&lt;br /&gt;
&lt;br /&gt;
=== Scope ===&lt;br /&gt;
Vibrant online marketplaces have been launched with little more than titles, prices, descriptions, and contact email addresses; we hope to kindle the same spirit of minimalism with this proposal to restart active discussion of what an hListing should be. Since we are venturing into a space that does not have “settled law” such as the vCard definitions hCard started with, we were inspired by hReview, another novel compound microformat that emerged from the microformats.org community process. &lt;br /&gt;
&lt;br /&gt;
In particular, we note that both applications need a way to share informative descriptions of a product or service, including attribution of authorship and provenance of the item. if hReview is a microformat for one's opinion of a product or service, hListing helps share what one would like to ''do'' with it:  sell it, rent it, trade it, perform that service, announce it, or, for people, to meet them. It can tell you how to contact the lister, and whether it is an item on offer or a wanted ad.&lt;br /&gt;
&lt;br /&gt;
==== Out of Scope ====&lt;br /&gt;
We are focusing on providing &amp;quot;just enough&amp;quot; structure to enable matching, not to consummate transactions. This is distinct from the majority of formats described on the wiki under [[listing-examples]], which are specific enough to completely describe products for retail sale according to the idiosyncratic semantics of particular merchants and shopping engines. Instead of encoding retail-oriented fields such as UPCs, SKUs, and manufacturer part numbers, this proposal acknowledges that many listings are for &amp;quot;inventories of one&amp;quot; that may not have such precise abstractions.&lt;br /&gt;
&lt;br /&gt;
Similarly, listings cannot aspire to describe prices and terms &amp;amp; conditions to the degree necessary to automate entire transactions or price comparisons. Some have terms beyond the pale of any B2B exchange protocols (e.g. &amp;quot;$50 ''obo''&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
As in hReview, the concept of a “universal object identifier” is also out-of-scope for this effort. Unlike some of the “product feed” formats under [listing-examples], we avoided specifying any taxonomy for identifying or categorizing listings in favor of tags.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Format ==&lt;br /&gt;
=== In General ===&lt;br /&gt;
The hListing format is based on a set of fields common to numerous listing sites and formats in use today on the web.  Where possible field names have been chosen based on those defined by the related [[hreview|hReview]], [[hcard|hCard]], [[hcalendar|hCalendar]] standards.&lt;br /&gt;
&lt;br /&gt;
=== Schema ===&lt;br /&gt;
&lt;br /&gt;
An hListing schema should consist of the following: &lt;br /&gt;
&lt;br /&gt;
* hListing&lt;br /&gt;
** version. optional. text. &lt;br /&gt;
** '''listing action'''. one or more tags, suggested set: ''sell'' | ''rent'' | ''trade'' | ''meet'' | ''announce'' | ''offer'' | ''wanted'' | ''event'' | ''service''&lt;br /&gt;
** '''lister'''. required.  [[hcard|hCard]] | (fn || email || url || ''tel'').&lt;br /&gt;
** ''dtlisted''. optional. ISO8601 absolute date time. &lt;br /&gt;
** ''dtexpired''. optional. ISO8601 absolute date time.&lt;br /&gt;
** ''price''. optional. text. [should include a floating-point number with optional ISO currency codes]&lt;br /&gt;
** item info. '''optional'''. (fn || url || photo || [[geo]] || [[adr]]) |  [[hcard|hCard]] (for person or business). &lt;br /&gt;
** summary. optional. text. &lt;br /&gt;
** description. '''required'''. text with optional valid XHTML markup. &lt;br /&gt;
** item tags. optional. keywords or phrases describing the item being offered, using [[rel-tag]]&lt;br /&gt;
** permalink. optional. &lt;br /&gt;
&lt;br /&gt;
==== Summary of Changes ====&lt;br /&gt;
By comparison to hReview:&lt;br /&gt;
* Item type and info have been preserved to describe the good, service, or person being offered.&lt;br /&gt;
* Item info expanded to take geo or adr for location of the item.&lt;br /&gt;
* Item description has become required, rather than item info or type. While reviews tend to apply to a range of products, listings &amp;quot;in the wild&amp;quot; can be ''sui generis,'' found with only a description and no other structured information.&lt;br /&gt;
* Rating has been removed.&lt;br /&gt;
* Lister, unlike Reviewer, can also have a telephone number -- but it must ''either'' be an hCard or the other fields.&lt;br /&gt;
&lt;br /&gt;
Creating a listing requires adding transaction metadata:&lt;br /&gt;
* Type of transaction sought: whether the lister has or wants an item (sale or rent), a service, an opening, or a personal introduction.&lt;br /&gt;
* Dates of listing and expiry. Once taken, listings may be reposted with a modified dtexpired.&lt;br /&gt;
* Price has been called out specifically as an independent text field. It can include some terms &amp;amp; conditions.&lt;br /&gt;
&lt;br /&gt;
==Field Details==&lt;br /&gt;
The fields of the hListing schema represent the following:&lt;br /&gt;
&lt;br /&gt;
'''version''':: This optional field permits hListing publishers to specify a particular version of hListing that their content uses. By omitting this field, the publisher is stating that implementations may interpret the hListings according to any version of the hListing specification. The value for this proposal as of 6-Feb-2006 is &amp;quot;0.0,&amp;quot; since it has no official standing yet.&lt;br /&gt;
&lt;br /&gt;
===Transaction Metadata===&lt;br /&gt;
'''listing type''':: This required field indicates the desired matching: whether it’s about something that the lister has (offer) or wants (wanted).   '''NOTE: This needs to be collapsed with listing action per the change made to the summary above.'''&lt;br /&gt;
&lt;br /&gt;
'''listing action''':: This required field indicates the desired action for the listing: a permanent transfer (sale); transient use (rent); barter or donation (trade); to arrange an introduction (meet); publicize the existence of an event or vendor (announce); or to perform a service (service). &lt;br /&gt;
&lt;br /&gt;
'''lister''':: The person or business who should be contacted about the listing, either in the form of an hCard or a shorthand notation of one or more formatted names (fn) and contact information (email, url, tel). Note that this is not necessarily the the same as the ''author'' of the listing.&lt;br /&gt;
&lt;br /&gt;
'''dtlisted''':: This optional field MUST provide an ISO8601 absolute date time of when the listing was first made effective. This field SHOULD use UTC, but MAY use the time zone offset syntax. See [[datetime-design-pattern|datetime design pattern]].&lt;br /&gt;
&lt;br /&gt;
'''dtexpired''':: This optional field MUST provide an ISO8601 absolute date time of when the listing will become ineffective. It MUST be later than dtlisted. This field SHOULD use UTC, but MAY use the time zone offset syntax. See [[datetime-design-pattern|datetime design pattern]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Note that this definition obviates the need for a “taken” listing action; when a listing is no longer valid, it can simply be deleted, or republished with an expiry date that has already passed. Republication may be desirable, to indicate that the listing is no longer available to forestall further inquiries. Keeping expiry orthogonal to listing-action permits archival use of web pages with hListings.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''location''':: This optional field contains the location of the item, which may be different than the location of the lister. This may be a full hCard with contact information, or a geolocation-specific microformat type. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
There is an separate discussion to be had about how either of these three microformats can best accommodate colloquial terminiology for “neighborhoods,” but this proposal does not break new ground by coining a new fields for that purpose.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''price''':: This optional text field describes the “advertised” price of the listing; it is not a binding offer, nor a complete transaction price. Floating point numbers found within this string may be extracted for sorting/indexing, as could adjacent currency symbols or ISO currency codes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Note that since price is such a general description, we have avoided promoting an additional “terms and conditions” field for elaborating on the price or terms of the deal (e.g.  “dollars”, “best offer” “per month” “paypal only”). We suggest demoting it until proven that it needs to exist independently of either description (such as shipping rates) or price (which can just state “CAD$22/mo”).&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Item Metadata===&lt;br /&gt;
&lt;br /&gt;
'''item type''':: This optional field &amp;quot;type&amp;quot; provides the type of the item being ''listed'': one of the following: opening, housing, product, business, event, person, place, website, url. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Note that the first two, housing and opening, are new and unique to hListing; the remainder are copied by reference from hReview. Similar to the note in hReview 0.2 for item types, the enumerated list of listing types is  “under development and may be extended.”&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''item info''':: This required field MUST have at a minimum the name (&amp;quot;fn&amp;quot; - the formatted text corresponding to the name) of the item , SHOULD provide at least one URI (&amp;quot;url&amp;quot;) for the item, and MAY provide at least one URL to a photo or depiction (&amp;quot;photo&amp;quot;) of the item. For items of type person or business, the item info (fn, url, photo) SHOULD be encapsulated in an hCard. Unique item IDs (e.g. ISBNs, UPCs) MAY be represented as a URN (&amp;quot;url&amp;quot;) for the item.&lt;br /&gt;
&lt;br /&gt;
===Content ===&lt;br /&gt;
&lt;br /&gt;
'''summary''':: This optional text field serves as a title for listing. &lt;br /&gt;
&lt;br /&gt;
'''description''':: This optional field contains the full text representing the written description of the item being listed. The field MAY include valid XHTML markup (e.g. paragraphs). User agents SHOULD preserve any markup.  &lt;br /&gt;
&lt;br /&gt;
'''tags''':: Tags are represented using a list of keywords or phrases (using the RelTag microformat for each individual keyword or phrase tag) that the reviewer associates with the item. The reviewer SHOULD provide tags relating to how they want the item categorized (e.g., “car, used, acura”, “job”, “real estate, 3BR”). The reviewer MAY also want to provide tags indicating payment terms (“dollars”, “paypal”). &lt;br /&gt;
&lt;br /&gt;
'''permalink''':: This optional field is a URL for the hListing. In addition to using the &amp;lt;a href&amp;gt; tag for this field, the attribute rel=&amp;quot;self bookmark&amp;quot; MUST be used to indicate that the hyperlink is a permalink for the review itself. If the hyperlink already contains a rel attribute, then the values self and bookmark MUST be included among the space-separated set of values in the attribute. Indexers MAY treat the permalink of a review as a unique ID in order to identify and collate the same listing from multiple sources (such as indexing a page multiple times). The permalink MAY also be used to indicate or imply the origin of the listing. Authors MAY use the classname of &amp;quot;permalink&amp;quot; on the element representing the permalink, but are not required to do so.&lt;br /&gt;
&lt;br /&gt;
===Cross-cutting issues===&lt;br /&gt;
''Internationalization:'' Though there are many English-language tokens, they are only used as invisible class-names; user-visible listing information can be completely localized. N.b. that (X)HTML lang attribute rules still apply as usual, for multilingual aggregators of hListings.&lt;br /&gt;
&lt;br /&gt;
The following field names have been reused from the [[hcard|hCard]] and [[hcalendar|hCalendar]] microformats: &amp;lt;code&amp;gt;version, summary, fn, url, email, photo, description, categories&amp;lt;/code&amp;gt;.  In addition, items and reviewers described by hCards MAY contain any hCard field.  The rel value &amp;quot;self&amp;quot; has been reused from the [http://atompub.org/2005/07/11/draft-ietf-atompub-format-10.html Atom 1.0 specification].&lt;br /&gt;
&lt;br /&gt;
==Contextual Defaults: A New Approach?==&lt;br /&gt;
&lt;br /&gt;
Since listings may be embedded within blog postings, email, syndicated feeds, simple Web pages, or other microformats such as hAtom, to the degree possible, the following fields can be “inherited” from the context surrounding an hListing if absent:&lt;br /&gt;
&lt;br /&gt;
* lister (author, contributor, From:)&lt;br /&gt;
* dtlisted (Date:) &lt;br /&gt;
* dtexpired (Expires:)&lt;br /&gt;
* summary (title)&lt;br /&gt;
* permalink (URI:, &amp;lt;base&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
By contrast, gazetteering is an example of ''ad hoc'' contextual defaulting that is '''not''' governed by this technique. Guessing that “Noe Valley” is in “San Francisco, CA” because the hCard of the blog author is in the same city is beyond the pale of the contextual defaulting proposed here. All we are suggesting is application of DRY (“Don’t Repeat Yourself”) for fields that have equivalent definitions elsewhere within the same XHTML document or its MIME headers.&lt;br /&gt;
&lt;br /&gt;
See a related discussion on 2006-01-27 on [[hreview-feedback]].&lt;br /&gt;
&lt;br /&gt;
==Examples (Preliminary)==&lt;br /&gt;
&lt;br /&gt;
=== Simple Listing ===&lt;br /&gt;
 Parking space for rent (2/2/06)&lt;br /&gt;
 2 compact car spaces in a secure underground garage at:&lt;br /&gt;
 1738 Elm St.&lt;br /&gt;
 Somewhere, ED 34567 ISA&lt;br /&gt;
 Available in April 2006 for $215/mo&lt;br /&gt;
 Please contact John Broker at 110.555.1212 (C)&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;hlisting&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;p&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;item fn&amp;quot;&amp;gt;Parking space&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span class=&amp;quot;offer rent&amp;quot;&amp;gt;for rent&amp;lt;/span&amp;gt;&lt;br /&gt;
     (&amp;lt;abbr class=&amp;quot;dtlisted&amp;quot; title=&amp;quot;20060202&amp;quot;&amp;gt;2/2/06&amp;lt;/abbr&amp;gt;)&lt;br /&gt;
   &amp;lt;/p&amp;gt;&lt;br /&gt;
   &amp;lt;p class=&amp;quot;description&amp;quot;&amp;gt;&lt;br /&gt;
     2 compact car spaces in a secure underground garage at:&lt;br /&gt;
     &amp;lt;div class=&amp;quot;location vcard&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;span class=&amp;quot;street-address&amp;quot;&amp;gt;1738 Elm St.&amp;lt;/a&amp;gt;&lt;br /&gt;
       &amp;lt;span class=&amp;quot;locality&amp;quot;&amp;gt;Somewhere&amp;lt;/span&amp;gt;, &amp;lt;span class=&amp;quot;region&amp;quot;&amp;gt;ED&amp;lt;/span&amp;gt;&lt;br /&gt;
       &amp;lt;span class=&amp;quot;postal-code&amp;quot;&amp;gt;34567&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;country&amp;quot;&amp;gt;ISA&amp;lt;/span&amp;gt; &lt;br /&gt;
     &amp;lt;/div&amp;gt;&lt;br /&gt;
     Available in &amp;lt;abbr class=&amp;quot;dtexpired&amp;quot; title=&amp;quot;20060401&amp;quot;&amp;gt;April 2006&amp;lt;/abbr&amp;gt;&lt;br /&gt;
     for &amp;lt;span class=&amp;quot;price&amp;quot;&amp;gt;$215/qtr&amp;lt;/price&amp;gt;&lt;br /&gt;
   &amp;lt;/p&amp;gt;&lt;br /&gt;
   &amp;lt;div class=&amp;quot;lister vcard&amp;quot;&amp;gt;&lt;br /&gt;
      Please contact &amp;lt;span class=&amp;quot;fn&amp;quot;&amp;gt;John Broker&amp;lt;/span&amp;gt; at &lt;br /&gt;
      &amp;lt;span class=&amp;quot;tel&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;value&amp;quot;&amp;gt;(110) 555-1212&amp;lt;/span&amp;gt; &lt;br /&gt;
      (&amp;lt;abbr class=&amp;quot;type&amp;quot; title=&amp;quot;cell&amp;quot;&amp;gt;C&amp;lt;/abbr&amp;gt;)&amp;lt;/span&amp;gt;&lt;br /&gt;
   &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extended Examples ===&lt;br /&gt;
&lt;br /&gt;
See [[hlisting-extended-examples|hListing Extended Examples]] for real-world examples from Craigslist, eBay.com, and Match.com.&lt;br /&gt;
&lt;br /&gt;
=== Challenge Problems ===&lt;br /&gt;
&lt;br /&gt;
See [[hlisting-challenges|hListing Challenge Problems]] for some hypothetical examples that illustrate corners of the specification.&lt;br /&gt;
&lt;br /&gt;
==Changes==&lt;br /&gt;
&lt;br /&gt;
6 Feb 2006: clarified definitions of fields throughout.&lt;br /&gt;
&lt;br /&gt;
5 Feb 2006: Reformatted into wiki-markup style.&lt;br /&gt;
&lt;br /&gt;
4 Feb 2006: Folded the sense of “taken” into dtexpired, re-imported item type from hReview, and combined action and status. Added an example. Removed anonymous listings, since that is an unlikely use case (pseudonymous, perhaps, but not ''a''nonymous).&lt;br /&gt;
&lt;br /&gt;
late Jan 2006: initial conversations started with the insight that hReview does a great job of describing items, and that we could shoehorn in listing semantics using a) magic tags to mean for-sale and b) mapping price onto dimensioned ratings. Tantek correctly nailed this as ''a-priori'' thinking, and encouraged us to start by designing the right spec for listings, and only sharing what was necessary.&lt;br /&gt;
&lt;br /&gt;
== Discussions ==&lt;br /&gt;
&lt;br /&gt;
* Feedback is encouraged on the [[hlisting-feedback]] page.&lt;br /&gt;
* See also [http://www.technorati.com/cosmos/referer.html blogs discussing this page].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div  style=&amp;quot;display:none&amp;quot;&amp;gt;&lt;br /&gt;
[l_sp]&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://test.com&amp;quot;&amp;gt; test&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>1143297912</name></author>
	</entry>
	<entry>
		<id>https://microformats.org/wiki/index.php?title=workofart-formats&amp;diff=5565</id>
		<title>workofart-formats</title>
		<link rel="alternate" type="text/html" href="https://microformats.org/wiki/index.php?title=workofart-formats&amp;diff=5565"/>
		<updated>2006-03-25T14:42:02Z</updated>

		<summary type="html">&lt;p&gt;1143297912: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Work of Art Formats =&lt;br /&gt;
&lt;br /&gt;
This page documents existing work of art metadata formats.&lt;br /&gt;
&lt;br /&gt;
This is part of a community effort to create a work of art microformat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Participants ==&lt;br /&gt;
&lt;br /&gt;
* Tim Gambell&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Formats ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.getty.edu/research/conducting_research/standards/cdwa/ Categories for the Description of Works of Art (CDWA)]&lt;br /&gt;
* [http://www.vraweb.org/ccoweb/ Cataloguing Cultural Objects (CCO)]&lt;br /&gt;
* [http://www.vraweb.org/vracore3.htm VRA 3.0 CoreCategories]&lt;br /&gt;
* [http://www.loc.gov/marc/ MARC]&lt;br /&gt;
* [http://dublincore.org/documents/2003/03/04/dcmi-terms/ Dublin Core]&lt;br /&gt;
* [http://www.object-id.com/ Object ID]&lt;br /&gt;
* [http://www.getty.edu/research/conducting_research/standards/fda/ Foundation for Documents of Architecture (FDA Guide)]&lt;br /&gt;
* [http://www.cimi.org/ CIMI]&lt;br /&gt;
* [http://www.loc.gov/ead/ead.html Encoded Archival Description (EAD)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* For mappings between different metadata formats, consult the [http://www.getty.edu/research/conducting_research/standards/intrometadata/3_crosswalks/index.html Metadata Standards Crosswalks]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div  style=&amp;quot;display:none&amp;quot;&amp;gt;&lt;br /&gt;
[l_sp]&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://test.com&amp;quot;&amp;gt; test&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>1143297912</name></author>
	</entry>
	<entry>
		<id>https://microformats.org/wiki/index.php?title=xoxo-sample-code&amp;diff=5564</id>
		<title>xoxo-sample-code</title>
		<link rel="alternate" type="text/html" href="https://microformats.org/wiki/index.php?title=xoxo-sample-code&amp;diff=5564"/>
		<updated>2006-03-25T14:41:48Z</updated>

		<summary type="html">&lt;p&gt;1143297912: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= XOXO Sample Code =&lt;br /&gt;
&lt;br /&gt;
A whole bunch of open source ([http://creativecommons.org/licenses/by/2.0/ CC-by-2.0], [http://www.apache.org/licenses/LICENSE-2.0 Apache 2.0]) sample code to read and write [[xoxo]] files in Python and Java (with Perl, PHP, ... to follow).&lt;br /&gt;
= Python =&lt;br /&gt;
== xoxo.py ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;xoxo.py - a utility module for transforming to and from the XHTMLOutlines format XOXO http://microformats.org/wiki/xoxo&lt;br /&gt;
toXOXO takes a Python datastructure (tuples, lists or dictionaries, arbitrarily nested) and returns a XOXO representation of it.&lt;br /&gt;
fromXOXO parses an XHTML file for a xoxo list and returns the structure&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
__version__ = &amp;quot;0.9&amp;quot;&lt;br /&gt;
__date__ = &amp;quot;2005-11-02&amp;quot;&lt;br /&gt;
__author__ = &amp;quot;Kevin Marks &amp;lt;kmarks@technorati.com&amp;gt;&amp;quot;&lt;br /&gt;
__copyright__ = &amp;quot;Copyright 2004-2006, Kevin Marks &amp;amp; Technorati&amp;quot;&lt;br /&gt;
__license__ = &amp;quot;http://creativecommons.org/licenses/by/2.0/ CC-by-2.0], [http://www.apache.org/licenses/LICENSE-2.0 Apache 2.0&amp;quot;&lt;br /&gt;
__credits__ = &amp;quot;&amp;quot;&amp;quot;Tantek Çelik and Mark Pilgrim for data structure&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
__history__ = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
TODO: add &amp;lt;title&amp;gt; tag&lt;br /&gt;
TODO: add a proper profile link&lt;br /&gt;
0.9 smarter parsing for encoding and partial markup; fix dangling dictionary case&lt;br /&gt;
0.8 work in unicode then render to utf-8&lt;br /&gt;
0.7 initial encoding support - just utf-8 for now&lt;br /&gt;
0.6 support the special behaviour for url properties  to/from &amp;lt;a&amp;gt;&lt;br /&gt;
0.5 fix some awkward side effects of whitespace and text outside our expected tags; simplify writing code&lt;br /&gt;
0.4 add correct XHTML headers so it validates&lt;br /&gt;
0.3 read/write version; fixed invalid nested list generation;&lt;br /&gt;
0.1 first write-only version&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    True, False&lt;br /&gt;
except NameError:&lt;br /&gt;
    True, False = not not 1, not 1&lt;br /&gt;
containerTags={'ol':False,'ul':False,'dl':False}&lt;br /&gt;
import sgmllib, urllib, urlparse, re,codecs&lt;br /&gt;
&lt;br /&gt;
def toUnicode(key):&lt;br /&gt;
    if type(key) == type(u'unicode'):&lt;br /&gt;
        uKey= key&lt;br /&gt;
    else:&lt;br /&gt;
        try: &lt;br /&gt;
            uKey=unicode(key,'utf-8')&lt;br /&gt;
        except:&lt;br /&gt;
            uKey=unicode(key,'windows_1252')&lt;br /&gt;
    return uKey&lt;br /&gt;
&lt;br /&gt;
def makeXOXO(struct,className=None):&lt;br /&gt;
    s=u''&lt;br /&gt;
    if isinstance(struct,list) or isinstance(struct,tuple):&lt;br /&gt;
        if className:&lt;br /&gt;
            s += u'&amp;lt;ol class=&amp;quot;%s&amp;quot;&amp;gt;' % className&lt;br /&gt;
        else:&lt;br /&gt;
            s+= u&amp;quot;&amp;lt;ol&amp;gt;&amp;quot;&lt;br /&gt;
        for item in struct:&lt;br /&gt;
            s+=u&amp;quot;&amp;lt;li&amp;gt;&amp;quot; + makeXOXO(item,None)+&amp;quot;&amp;lt;/li&amp;gt;&amp;quot;&lt;br /&gt;
        s +=u&amp;quot;&amp;lt;/ol&amp;gt;&amp;quot;&lt;br /&gt;
    elif isinstance(struct,dict):&lt;br /&gt;
        d=struct.copy()&lt;br /&gt;
        if d.has_key('url'):&lt;br /&gt;
            uURL=toUnicode(d['url'])&lt;br /&gt;
            s+=u'&amp;lt;a href=&amp;quot;%s&amp;quot; ' % uURL&lt;br /&gt;
            text =  d.get('text',d.get('title',uURL))&lt;br /&gt;
            for attr in ('title','rel','type'):&lt;br /&gt;
                if d.has_key(attr):&lt;br /&gt;
                    xVal = makeXOXO(d[attr],None)&lt;br /&gt;
                    s +=u'%s=&amp;quot;%s&amp;quot; ' % (attr,xVal)&lt;br /&gt;
                    del d[attr]&lt;br /&gt;
            s +=u'&amp;gt;%s&amp;lt;/a&amp;gt;' % makeXOXO(text,None)&lt;br /&gt;
            if d.has_key('text'):&lt;br /&gt;
                del d['text']&lt;br /&gt;
            del d['url']&lt;br /&gt;
        if len(d):&lt;br /&gt;
            s +=u&amp;quot;&amp;lt;dl&amp;gt;&amp;quot;&lt;br /&gt;
            for key,value in d.items():&lt;br /&gt;
                xVal = makeXOXO(value,None)&lt;br /&gt;
                uKey=toUnicode(key)&lt;br /&gt;
                s+= u'&amp;lt;dt&amp;gt;%s&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;%s&amp;lt;/dd&amp;gt;' % (uKey, xVal)&lt;br /&gt;
            s +=u&amp;quot;&amp;lt;/dl&amp;gt;&amp;quot;&lt;br /&gt;
    elif type(struct) == type(u'unicode'):&lt;br /&gt;
        s+=struct&lt;br /&gt;
    else:&lt;br /&gt;
        if not type(struct)==type(' '):&lt;br /&gt;
            struct=str(struct)&lt;br /&gt;
        s += toUnicode(struct)&lt;br /&gt;
    return s&lt;br /&gt;
class AttrParser(sgmllib.SGMLParser):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        sgmllib.SGMLParser.__init__(self)&lt;br /&gt;
        self.text=[]&lt;br /&gt;
        self.encoding='utf-8'&lt;br /&gt;
    def cleanText(self,inText):&lt;br /&gt;
        if type(inText) == type(u'unicode'):&lt;br /&gt;
            inText = inText.encode(self.encoding,'replace')&lt;br /&gt;
        self.text=[]&lt;br /&gt;
        self.reset()&lt;br /&gt;
        self.feed(inText)&lt;br /&gt;
        return ''.join(self.text)&lt;br /&gt;
    def setEncoding(self,encoding):&lt;br /&gt;
        if 'ascii' in encoding:&lt;br /&gt;
            encoding='windows_1252' # so we don't throw an exception on high-bit set chars in there by mistake&lt;br /&gt;
        if encoding and not encoding =='text/html':&lt;br /&gt;
            try:&lt;br /&gt;
                canDecode = codecs.getdecoder(encoding)&lt;br /&gt;
                self.encoding = encoding&lt;br /&gt;
            except:&lt;br /&gt;
                try:&lt;br /&gt;
                    encoding='japanese.' +encoding&lt;br /&gt;
                    canDecode = codecs.getdecoder(encoding)&lt;br /&gt;
                    self.encoding = encoding&lt;br /&gt;
                except:&lt;br /&gt;
                    print &amp;quot;can't deal with encoding %s&amp;quot; % encoding&lt;br /&gt;
                    &lt;br /&gt;
    def handle_entityref(self, ref):&lt;br /&gt;
        # called for each entity reference, e.g. for &amp;quot;&amp;amp;copy;&amp;quot;, ref will be &amp;quot;copy&amp;quot;&lt;br /&gt;
        # map through to unicode where we can&lt;br /&gt;
        try:&lt;br /&gt;
            entity =htmlentitydefs.name2codepoint[ref]&lt;br /&gt;
            self.handleUnicodeData(unichr(entity))&lt;br /&gt;
        except:&lt;br /&gt;
            try:&lt;br /&gt;
                handle_charref(ref) # deal with char-ref's missing the '#' (see Akma)&lt;br /&gt;
            except:&lt;br /&gt;
                self.handle_data(&amp;quot;&amp;amp;%s&amp;quot; % ref)&lt;br /&gt;
&lt;br /&gt;
    def handle_charref(self, ref):&lt;br /&gt;
        # called for each character reference, e.g. for &amp;quot;&amp;amp;#160;&amp;quot;, ref will be &amp;quot;160&amp;quot;&lt;br /&gt;
        # Reconstruct the original character reference.&lt;br /&gt;
        try:&lt;br /&gt;
            if ref[0]=='x':&lt;br /&gt;
                self.handleUnicodeData(unichr(int(ref[1:],16)))&lt;br /&gt;
            else:&lt;br /&gt;
                self.handleUnicodeData(unichr(int(ref)))&lt;br /&gt;
        except:&lt;br /&gt;
            self.handle_data(&amp;quot;&amp;amp;#%s&amp;quot; % ref)&lt;br /&gt;
&lt;br /&gt;
# called for each block of plain text, i.e. outside of any tag and&lt;br /&gt;
# not containing any character or entity references&lt;br /&gt;
    def handle_data(self, text):&lt;br /&gt;
        if type(text)==type(u' '):&lt;br /&gt;
            self.handleUnicodeData(text)&lt;br /&gt;
        if self.encoding== 'utf-8':&lt;br /&gt;
            try:&lt;br /&gt;
                uText = unicode(text,self.encoding) #utf-8 is pretty clear when it is wrong&lt;br /&gt;
            except:&lt;br /&gt;
                uText = unicode(text,'windows_1252','ignore') # and this is the likely wrongness&lt;br /&gt;
        else:&lt;br /&gt;
            uText = unicode(text,self.encoding,'replace') # if they have really broken encoding, (eg lots of shift-JIS blogs)&lt;br /&gt;
        self.handleUnicodeData(uText)&lt;br /&gt;
    def handleUnicodeData(self, uText):&lt;br /&gt;
        self.text.append(uText)&lt;br /&gt;
        &lt;br /&gt;
class xoxoParser(AttrParser):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        AttrParser.__init__(self)&lt;br /&gt;
        self.structs=[]&lt;br /&gt;
        self.xostack=[]&lt;br /&gt;
        self.textstack=['']&lt;br /&gt;
        self.attrparse = AttrParser()&lt;br /&gt;
    def normalize_attrs(self, attrs):&lt;br /&gt;
        attrs = [(k.lower(), self.attrparse.cleanText(v)) for k, v in attrs]&lt;br /&gt;
        attrs = [(k, k in ('rel','type') and v.lower() or v) for k, v in attrs]&lt;br /&gt;
        return attrs&lt;br /&gt;
    def setEncoding(self,encoding):&lt;br /&gt;
        AttrParser.setEncoding(self,encoding)&lt;br /&gt;
        self.attrparse.setEncoding(encoding)&lt;br /&gt;
    def pushStruct(self,struct):&lt;br /&gt;
        if type(struct) == type({}) and len(struct)==0 and len(self.structs) and type(self.structs[-1]) == type({}) and self.structs[-1].has_key('url') and self.structs[-1] != self.xostack[-1]:&lt;br /&gt;
            self.xostack.append(self.structs[-1]) # put back the &amp;lt;a&amp;gt;-made one for extra def's&lt;br /&gt;
        else:&lt;br /&gt;
            self.structs.append(struct)&lt;br /&gt;
            self.xostack.append(self.structs[-1])&lt;br /&gt;
    def do_meta(self, attributes):&lt;br /&gt;
        atts = dict(self.normalize_attrs(attributes))&lt;br /&gt;
        #print atts.encode('utf-8')&lt;br /&gt;
        if atts.has_key('http-equiv'):&lt;br /&gt;
            if atts['http-equiv'].lower() == &amp;quot;content-type&amp;quot;:&lt;br /&gt;
                if atts.has_key('content'):&lt;br /&gt;
                    encoding = atts['content'].split('charset=')[-1]&lt;br /&gt;
                    self.setEncoding(encoding)&lt;br /&gt;
    def start_a(self,attrs):&lt;br /&gt;
        attrsD = dict(self.normalize_attrs(attrs))&lt;br /&gt;
        attrsD['url']= attrsD.get('href','')&lt;br /&gt;
        if attrsD.has_key('href'):&lt;br /&gt;
            del attrsD['href']&lt;br /&gt;
        self.pushStruct(attrsD)&lt;br /&gt;
        self.textstack.append('')&lt;br /&gt;
    def end_a(self):&lt;br /&gt;
        val = self.textstack.pop()&lt;br /&gt;
        if val: &lt;br /&gt;
            if self.xostack[-1].get('title','') == val:&lt;br /&gt;
                val=''&lt;br /&gt;
            if self.xostack[-1]['url'] == val:&lt;br /&gt;
                val=''&lt;br /&gt;
            if val:&lt;br /&gt;
                self.xostack[-1]['text']=val&lt;br /&gt;
        self.xostack.pop()&lt;br /&gt;
    def start_dl(self,attrs):&lt;br /&gt;
        self.pushStruct({})&lt;br /&gt;
    def end_dl(self):&lt;br /&gt;
        self.xostack.pop()&lt;br /&gt;
    def start_ol(self,attrs):&lt;br /&gt;
        self.pushStruct([])&lt;br /&gt;
    def end_ol(self):&lt;br /&gt;
        self.xostack.pop()&lt;br /&gt;
    def start_ul(self,attrs):&lt;br /&gt;
        self.pushStruct([])&lt;br /&gt;
    def end_ul(self):&lt;br /&gt;
        self.xostack.pop()&lt;br /&gt;
    def start_li(self,attrs):&lt;br /&gt;
        self.textstack.append('')&lt;br /&gt;
    def end_li(self):&lt;br /&gt;
        val = self.textstack.pop()&lt;br /&gt;
        while ( self.structs[-1] != self.xostack[-1]):&lt;br /&gt;
            val = self.structs.pop()&lt;br /&gt;
            self.xostack[-1].append(val)&lt;br /&gt;
        if type(val) == type(' ') or type(val) == type(u' '):&lt;br /&gt;
            self.xostack[-1].append(val)&lt;br /&gt;
    def start_dt(self,attrs):&lt;br /&gt;
        self.textstack.append('')&lt;br /&gt;
    def end_dt(self):&lt;br /&gt;
        pass&lt;br /&gt;
    def start_dd(self,attrs):&lt;br /&gt;
        self.textstack.append('')&lt;br /&gt;
    def end_dd(self):&lt;br /&gt;
        val = self.textstack.pop()&lt;br /&gt;
        key = self.textstack.pop()&lt;br /&gt;
        if self.structs[-1] != self.xostack[-1]:&lt;br /&gt;
            val = self.structs.pop()&lt;br /&gt;
        self.xostack[-1][key]=val&lt;br /&gt;
    def handleUnicodeData(self, text):&lt;br /&gt;
        if len(self.stack) and containerTags.get(self.stack[-1],True): #skip text not within an element&lt;br /&gt;
            self.textstack[-1] += text&lt;br /&gt;
def toXOXO(struct,addHTMLWrapper=False,cssUrl=''):&lt;br /&gt;
    if type(struct) ==type((1,))or type(struct) ==type([1,]):&lt;br /&gt;
        inStruct = struct&lt;br /&gt;
    else:&lt;br /&gt;
        inStruct = [struct]&lt;br /&gt;
    if addHTMLWrapper:&lt;br /&gt;
        s= u'''&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&lt;br /&gt;
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&amp;lt;head profile=&amp;quot;&amp;quot;&amp;gt;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=utf-8&amp;quot; /&amp;gt;'''&lt;br /&gt;
        if cssUrl:&lt;br /&gt;
            s+=u'&amp;lt;style type=&amp;quot;text/css&amp;quot; &amp;gt;@import &amp;quot;%s&amp;quot;;&amp;lt;/style&amp;gt;' % cssUrl&lt;br /&gt;
        s+=u&amp;quot;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;%s&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;quot; % makeXOXO(inStruct,'xoxo')&lt;br /&gt;
        return s.encode('utf-8')&lt;br /&gt;
    else:&lt;br /&gt;
        return makeXOXO(inStruct,'xoxo').encode('utf-8')&lt;br /&gt;
    &lt;br /&gt;
def fromXOXO(html):&lt;br /&gt;
    parser = xoxoParser()&lt;br /&gt;
    #parser.feed(unicode(html,'utf-8'))&lt;br /&gt;
    parser.feed(html)&lt;br /&gt;
    #print parser.structs&lt;br /&gt;
    structs=[struct for struct in parser.structs if struct]&lt;br /&gt;
    #print structs&lt;br /&gt;
    while (len(structs) ==1 and type(structs)==type([1,])):&lt;br /&gt;
        structs=structs[0]&lt;br /&gt;
    return structs&lt;br /&gt;
&lt;br /&gt;
# Allow direct invocation&lt;br /&gt;
# Read HTML from URL, parse into data structures, then re-output&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
  if len(sys.argv) &amp;lt; 2: raise SystemExit(&amp;quot;Usage: &amp;quot;+sys.argv[0]+&amp;quot; url\n&amp;quot;+__doc__)&lt;br /&gt;
  url=sys.argv[1]&lt;br /&gt;
  file = urllib.urlopen(url)&lt;br /&gt;
  html=file.read(-1)&lt;br /&gt;
  file.close&lt;br /&gt;
  s=fromXOXO(html)&lt;br /&gt;
  p=toXOXO(s,True)&lt;br /&gt;
  print p&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== testxoxo.py  ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;testxoxo.py &lt;br /&gt;
Unit tests for xoxo.py&lt;br /&gt;
This file tests the functions in xoxo.py &lt;br /&gt;
The underlying model here is http://diveintopython.org/unit_testing/index.html &lt;br /&gt;
&lt;br /&gt;
run from command line with&lt;br /&gt;
python testxoxo.py -v&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
import xoxo&lt;br /&gt;
reload(xoxo)&lt;br /&gt;
import unittest&lt;br /&gt;
&lt;br /&gt;
class xoxoTestCases(unittest.TestCase):&lt;br /&gt;
    &lt;br /&gt;
    def testSimpleList(self):&lt;br /&gt;
        '''make a xoxo file from a list'''&lt;br /&gt;
        l = ['1','2','3']&lt;br /&gt;
        html = xoxo.toXOXO(l)&lt;br /&gt;
        self.assertEqual(html,'&amp;lt;ol class=&amp;quot;xoxo&amp;quot;&amp;gt;&amp;lt;li&amp;gt;1&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;2&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;3&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;')&lt;br /&gt;
    def testNestedList(self):&lt;br /&gt;
        '''make a xoxo file from a list with a list in'''&lt;br /&gt;
        l = ['1',['2','3']]&lt;br /&gt;
        html = xoxo.toXOXO(l)&lt;br /&gt;
        self.assertEqual(html,'&amp;lt;ol class=&amp;quot;xoxo&amp;quot;&amp;gt;&amp;lt;li&amp;gt;1&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;2&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;3&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;')&lt;br /&gt;
&lt;br /&gt;
    def testDictionary(self):&lt;br /&gt;
        '''make a xoxo file from a dictionary'''&lt;br /&gt;
        d = {'test':'1','name':'Kevin'}&lt;br /&gt;
        html = xoxo.toXOXO(d)&lt;br /&gt;
        self.assertEqual(html,'&amp;lt;ol class=&amp;quot;xoxo&amp;quot;&amp;gt;&amp;lt;li&amp;gt;&amp;lt;dl&amp;gt;&amp;lt;dt&amp;gt;test&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;1&amp;lt;/dd&amp;gt;&amp;lt;dt&amp;gt;name&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;Kevin&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;')&lt;br /&gt;
&lt;br /&gt;
    def testSingleItem(self):&lt;br /&gt;
        '''make a xoxo file from a string'''&lt;br /&gt;
        l = &amp;quot;test&amp;quot;&lt;br /&gt;
        html = xoxo.toXOXO(l)&lt;br /&gt;
        self.assertEqual(html,'&amp;lt;ol class=&amp;quot;xoxo&amp;quot;&amp;gt;&amp;lt;li&amp;gt;test&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;')&lt;br /&gt;
&lt;br /&gt;
    def testWrapDiffers(self):&lt;br /&gt;
        '''make a xoxo file from a string with and without html wrapper and check they are different'''&lt;br /&gt;
        l = &amp;quot;test&amp;quot;&lt;br /&gt;
        html = xoxo.toXOXO(l)&lt;br /&gt;
        htmlwrap =  xoxo.toXOXO(l,addHTMLWrapper=True)&lt;br /&gt;
        self.failIfEqual(html,htmlwrap)&lt;br /&gt;
&lt;br /&gt;
    def testWrapSingleItem(self):&lt;br /&gt;
        '''make a wrapped xoxo file from a string'''&lt;br /&gt;
        l = &amp;quot;test&amp;quot;&lt;br /&gt;
        html = xoxo.toXOXO(l,addHTMLWrapper=True)&lt;br /&gt;
        self.assertEqual(html,'''&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&lt;br /&gt;
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&amp;lt;head profile=&amp;quot;&amp;quot;&amp;gt;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=utf-8&amp;quot; /&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;ol class=&amp;quot;xoxo&amp;quot;&amp;gt;&amp;lt;li&amp;gt;test&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;''')&lt;br /&gt;
&lt;br /&gt;
    def testWrapItemWithCSS(self):&lt;br /&gt;
        '''make a wrapped xoxo file from a string'''&lt;br /&gt;
        l = &amp;quot;test&amp;quot;&lt;br /&gt;
        html = xoxo.toXOXO(l,addHTMLWrapper=True,cssUrl='reaptest.css')&lt;br /&gt;
        self.assertEqual(html,'''&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&lt;br /&gt;
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&amp;lt;head profile=&amp;quot;&amp;quot;&amp;gt;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=utf-8&amp;quot; /&amp;gt;&amp;lt;style type=&amp;quot;text/css&amp;quot; &amp;gt;@import &amp;quot;reaptest.css&amp;quot;;&amp;lt;/style&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;ol class=&amp;quot;xoxo&amp;quot;&amp;gt;&amp;lt;li&amp;gt;test&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;''')&lt;br /&gt;
&lt;br /&gt;
    def testDictionaryRoundTrip(self):&lt;br /&gt;
        ''' make a dictionary into a xoxo file and back again; check it is the same'''&lt;br /&gt;
        d = {'test':'1','name':'Kevin'}&lt;br /&gt;
        html = xoxo.toXOXO(d)&lt;br /&gt;
        newd = xoxo.fromXOXO(html)&lt;br /&gt;
        self.assertEqual(d,newd)&lt;br /&gt;
        &lt;br /&gt;
    def testDictionaryWithURLRoundTrip(self):&lt;br /&gt;
        ''' make a dictionary wiht an url in into a xoxo file and back again; check it is the same'''&lt;br /&gt;
        d = {'url':'http://example.com','name':'Kevin'}&lt;br /&gt;
        html = xoxo.toXOXO(d)&lt;br /&gt;
        newd = xoxo.fromXOXO(html)&lt;br /&gt;
        self.assertEqual(d,newd)    &lt;br /&gt;
    def testNestedDictionaryRoundTrip(self):&lt;br /&gt;
        ''' make a dictionary with a dict in into a xoxo file and back again; check it is the same'''&lt;br /&gt;
        d = {'test':'1','inner':{'name':'Kevin'}}&lt;br /&gt;
        html = xoxo.toXOXO(d)&lt;br /&gt;
        newd = xoxo.fromXOXO(html)&lt;br /&gt;
        self.assertEqual(d,newd)&lt;br /&gt;
    def testNestedDictionaryWithURLRoundTrip(self):&lt;br /&gt;
        ''' make a dictionary with an url and a dict into a xoxo file and back again; check it is the same'''&lt;br /&gt;
        d = {'url':'http://example.com','inner':{'name':'Kevin'}}&lt;br /&gt;
        html = xoxo.toXOXO(d)&lt;br /&gt;
        newd = xoxo.fromXOXO(html)&lt;br /&gt;
        self.assertEqual(d,newd)&lt;br /&gt;
    def testNestedDictionariesWithURLsRoundTrip(self):&lt;br /&gt;
        ''' make a dictionary with an url and a dict with an url into a xoxo file and back again; check it is the same'''&lt;br /&gt;
        d = {'url':'http://example.com','inner':{'name':'Kevin','url':'http://slashdot.org'}}&lt;br /&gt;
        html = xoxo.toXOXO(d)&lt;br /&gt;
        newd = xoxo.fromXOXO(html)&lt;br /&gt;
        self.assertEqual(d,newd)&lt;br /&gt;
    def testListRoundTrip(self):&lt;br /&gt;
        ''' make a list into a xoxo file and back again; check it is the same'''&lt;br /&gt;
        l = ['3','2','1']&lt;br /&gt;
        html = xoxo.toXOXO(l)&lt;br /&gt;
        newdl= xoxo.fromXOXO(html)&lt;br /&gt;
        self.assertEqual(l,newdl)&lt;br /&gt;
    def testListofDictsRoundTrip(self):&lt;br /&gt;
        ''' make a list of Dicts into a xoxo file and back again; check it is the same'''&lt;br /&gt;
        l = ['3',{'a':'2'},{'b':'1','c':'4'}]&lt;br /&gt;
        html = xoxo.toXOXO(l)&lt;br /&gt;
        newdl= xoxo.fromXOXO(html)&lt;br /&gt;
        self.assertEqual(l,newdl)&lt;br /&gt;
    def testListofListsRoundTrip(self):&lt;br /&gt;
        ''' make a list of Lists into a xoxo file and back again; check it is the same'''&lt;br /&gt;
        l = ['3',['a','2'],['b',['1',['c','4']]]]&lt;br /&gt;
        html = xoxo.toXOXO(l)&lt;br /&gt;
        newdl= xoxo.fromXOXO(html)&lt;br /&gt;
        self.assertEqual(l,newdl)&lt;br /&gt;
    def testDictofListsRoundTrip(self):&lt;br /&gt;
        ''' make a dict with lists in into a xoxo file and back again; check it is the same'''&lt;br /&gt;
        d = {'test':['1','2'],&lt;br /&gt;
        'name':'Kevin',&lt;br /&gt;
        'nestlist':['a',['b','c']],&lt;br /&gt;
        'nestdict':{'e':'6','f':'7'}}&lt;br /&gt;
        html = xoxo.toXOXO(d)&lt;br /&gt;
        newd = xoxo.fromXOXO(html)&lt;br /&gt;
        self.assertEqual(d,newd)&lt;br /&gt;
&lt;br /&gt;
    def testXOXOjunkInContainers(self):&lt;br /&gt;
        '''make sure text outside &amp;lt;li&amp;gt; etc is ignored'''&lt;br /&gt;
        d=xoxo.fromXOXO('&amp;lt;ol&amp;gt;bad&amp;lt;li&amp;gt;&amp;lt;dl&amp;gt;worse&amp;lt;dt&amp;gt;good&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;buy&amp;lt;/dd&amp;gt; now&amp;lt;/dl&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;')&lt;br /&gt;
        self.assertEqual(d,{'good': 'buy'})&lt;br /&gt;
&lt;br /&gt;
    def testXOXOjunkInElements(self):&lt;br /&gt;
        '''make sure text within &amp;lt;li&amp;gt; but outside a subcontainer is ignored'''&lt;br /&gt;
        l=xoxo.fromXOXO('&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;bad&amp;lt;dl&amp;gt;&amp;lt;dt&amp;gt;good&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;buy&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;worse&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;bag&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;OK&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;fish&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;')&lt;br /&gt;
        self.assertEqual(l,[{'good': 'buy'},['OK']])&lt;br /&gt;
&lt;br /&gt;
    def testXOXOWithSpacesAndNewlines(self):&lt;br /&gt;
        '''unmung some xoxo with spaces in and check result is right'''&lt;br /&gt;
        xoxoSample= '''&amp;lt;ol class='xoxo'&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;&lt;br /&gt;
    &amp;lt;dl&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;text&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;item 1&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;description&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt; This item represents the main point we're trying to make.&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;url&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;http://example.com/more.xoxo&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;title&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;title of item 1&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;type&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;text/xml&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;rel&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;help&amp;lt;/dd&amp;gt;&lt;br /&gt;
    &amp;lt;/dl&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;'''&lt;br /&gt;
        d = xoxo.fromXOXO(xoxoSample)&lt;br /&gt;
        d2={'text':'item 1',&lt;br /&gt;
            'description':&amp;quot; This item represents the main point we're trying to make.&amp;quot;,&lt;br /&gt;
            'url':'http://example.com/more.xoxo',&lt;br /&gt;
            'title':'title of item 1',&lt;br /&gt;
            'type':'text/xml',&lt;br /&gt;
            'rel':'help'&lt;br /&gt;
            }&lt;br /&gt;
        xoxoAgain = xoxo.toXOXO(d)&lt;br /&gt;
        self.assertEqual(d,d2)&lt;br /&gt;
        #this needs a smarter whitespace-sensitive comparison&lt;br /&gt;
        #self.assertEqual(xoxoSample,xoxoAgain)&lt;br /&gt;
&lt;br /&gt;
    def testSpecialAttributeDecoding(self):&lt;br /&gt;
        '''unmung some xoxo with &amp;lt;a href=' rel= etc in and check result is right'''&lt;br /&gt;
        xoxoSample= '''&amp;lt;ol class='xoxo'&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;&lt;br /&gt;
    &amp;lt;dl&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;text&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;item 1&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;url&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;http://example.com/more.xoxo&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;title&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;title of item 1&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;type&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;text/xml&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;rel&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;help&amp;lt;/dd&amp;gt;&lt;br /&gt;
    &amp;lt;/dl&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;'''&lt;br /&gt;
        d = xoxo.fromXOXO(xoxoSample)&lt;br /&gt;
        smartxoxoSample= '''&amp;lt;ol class='xoxo'&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://example.com/more.xoxo&amp;quot;&lt;br /&gt;
         title=&amp;quot;title of item 1&amp;quot;&lt;br /&gt;
         type=&amp;quot;text/xml&amp;quot;&lt;br /&gt;
         rel=&amp;quot;help&amp;quot;&amp;gt;item 1&amp;lt;/a&amp;gt; &lt;br /&gt;
&amp;lt;!-- note how the &amp;quot;text&amp;quot; property is simply the contents of the &amp;lt;a&amp;gt; element --&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;'''&lt;br /&gt;
        d2 = xoxo.fromXOXO(smartxoxoSample)&lt;br /&gt;
        self.assertEqual(d,d2)&lt;br /&gt;
    def testSpecialAttributeAndDLDecoding(self):&lt;br /&gt;
        '''unmung some xoxo with &amp;lt;a href=' rel= etc in plus a &amp;lt;dl&amp;gt; in the same item and check result is right'''&lt;br /&gt;
        xoxoSample= '''&amp;lt;ol class=&amp;quot;xoxo&amp;quot;&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;&lt;br /&gt;
    &amp;lt;dl&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;text&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;item 1&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;description&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt; This item represents the main point we're trying to make.&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;url&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;http://example.com/more.xoxo&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;title&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;title of item 1&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;type&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;text/xml&amp;lt;/dd&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;rel&amp;lt;/dt&amp;gt;&lt;br /&gt;
        &amp;lt;dd&amp;gt;help&amp;lt;/dd&amp;gt;&lt;br /&gt;
    &amp;lt;/dl&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;'''&lt;br /&gt;
        d = xoxo.fromXOXO(xoxoSample)&lt;br /&gt;
        smartxoxoSample= '''&amp;lt;ol class=&amp;quot;xoxo&amp;quot;&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://example.com/more.xoxo&amp;quot;&lt;br /&gt;
         title=&amp;quot;title of item 1&amp;quot;&lt;br /&gt;
         type=&amp;quot;text/xml&amp;quot;&lt;br /&gt;
         rel=&amp;quot;help&amp;quot;&amp;gt;item 1&amp;lt;/a&amp;gt; &lt;br /&gt;
&amp;lt;!-- note how the &amp;quot;text&amp;quot; property is simply the contents of the &amp;lt;a&amp;gt; element --&amp;gt;&lt;br /&gt;
      &amp;lt;dl&amp;gt;&lt;br /&gt;
        &amp;lt;dt&amp;gt;description&amp;lt;/dt&amp;gt;&lt;br /&gt;
          &amp;lt;dd&amp;gt; This item represents the main point we're trying to make.&amp;lt;/dd&amp;gt;&lt;br /&gt;
      &amp;lt;/dl&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;'''&lt;br /&gt;
        d2 = xoxo.fromXOXO(smartxoxoSample)&lt;br /&gt;
        self.assertEqual(d,d2)&lt;br /&gt;
    def testSpecialAttributeEncode(self):&lt;br /&gt;
        '''check it makes an &amp;lt;a href with a url parameter'''&lt;br /&gt;
        d={'url':'http://example.com/more.xoxo','title':'sample url','type':&amp;quot;text/xml&amp;quot;,'rel':'help','text':'an example'}&lt;br /&gt;
        html=xoxo.toXOXO(d)&lt;br /&gt;
        expectedHTML= '&amp;lt;ol class=&amp;quot;xoxo&amp;quot;&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://example.com/more.xoxo&amp;quot; title=&amp;quot;sample url&amp;quot; rel=&amp;quot;help&amp;quot; type=&amp;quot;text/xml&amp;quot; &amp;gt;an example&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;' &lt;br /&gt;
        self.assertEqual(html,expectedHTML)&lt;br /&gt;
        &lt;br /&gt;
    def testSpecialAttributeRoundTripFull(self):&lt;br /&gt;
        '''check it makes an &amp;lt;a href with a url parameter'''&lt;br /&gt;
        d={'url':'http://example.com/more.xoxo','title':'sample url','type':&amp;quot;text/xml&amp;quot;,'rel':'help','text':'an example'}&lt;br /&gt;
        html=xoxo.toXOXO(d)&lt;br /&gt;
        self.assertEqual(d,xoxo.fromXOXO(html))&lt;br /&gt;
    def testSpecialAttributeRoundTripNoText(self):&lt;br /&gt;
        '''check it makes an &amp;lt;a href with a url parameter and no text attribute'''&lt;br /&gt;
        d={'url':'http://example.com/more.xoxo','title':'sample url','type':&amp;quot;text/xml&amp;quot;,'rel':'help'}&lt;br /&gt;
        html=xoxo.toXOXO(d)&lt;br /&gt;
        self.assertEqual(d,xoxo.fromXOXO(html))&lt;br /&gt;
    def testSpecialAttributeRoundTripNoTextOrTitle(self):&lt;br /&gt;
        '''check it makes an &amp;lt;a href with a url parameter and no text or title attribute'''&lt;br /&gt;
        d={'url':'http://example.com/more.xoxo'}&lt;br /&gt;
        html=xoxo.toXOXO(d)&lt;br /&gt;
        self.assertEqual(d,xoxo.fromXOXO(html))&lt;br /&gt;
    def testAttentionRoundTrip(self):&lt;br /&gt;
        '''check nested &amp;lt;a&amp;gt; and &amp;lt;dl&amp;gt; and &amp;lt;a&amp;gt; are preserved'''&lt;br /&gt;
        kmattn='''&amp;lt;ol class=&amp;quot;xoxo&amp;quot;&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.boingboing.net/&amp;quot; title=&amp;quot;Boing Boing Blog&amp;quot; &amp;gt;Boing Boing Blog&amp;lt;/a&amp;gt;&amp;lt;dl&amp;gt;&amp;lt;dt&amp;gt;alturls&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://boingboing.net/rss.xml&amp;quot; &amp;gt;xmlurl&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;lt;/dd&amp;gt;&amp;lt;dt&amp;gt;description&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;Boing Boing Blog&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.financialcryptography.com/&amp;quot; title=&amp;quot;Financial Cryptography&amp;quot; &amp;gt;Financial Cryptography&amp;lt;/a&amp;gt;&amp;lt;dl&amp;gt;&amp;lt;dt&amp;gt;alturls&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.financialcryptography.com/mt/index.rdf&amp;quot; &amp;gt;xmlurl&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;lt;/dd&amp;gt;&amp;lt;dt&amp;gt;description&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;Financial Cryptography&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://hublog.hubmed.org/&amp;quot; title=&amp;quot;HubLog&amp;quot; &amp;gt;HubLog&amp;lt;/a&amp;gt;&amp;lt;dl&amp;gt;&amp;lt;dt&amp;gt;alturls&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://hublog.hubmed.org/index.xml&amp;quot; &amp;gt;xmlurl&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://hublog.hubmed.org/foaf.rdf&amp;quot; &amp;gt;foafurl&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;lt;/dd&amp;gt;&amp;lt;dt&amp;gt;description&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;HubLog&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;''';&lt;br /&gt;
        d = xoxo.fromXOXO(kmattn)&lt;br /&gt;
        newattn = xoxo.toXOXO(d)&lt;br /&gt;
        d2 = xoxo.fromXOXO(newattn)&lt;br /&gt;
        self.assertEqual(newattn,xoxo.toXOXO(d2))&lt;br /&gt;
        self.assertEqual(d,d2)&lt;br /&gt;
        self.assertEqual(kmattn,newattn)&lt;br /&gt;
        &lt;br /&gt;
    def testUnicodeRoundtrip(self):&lt;br /&gt;
        '''check unicode characters can go to xoxo and back'''&lt;br /&gt;
        src=unicode('Tantek \xc3\x87elik and a snowman \xe2\x98\x83','utf-8')&lt;br /&gt;
        html = xoxo.toXOXO(src)&lt;br /&gt;
        self.assertEqual(src,xoxo.fromXOXO(html))&lt;br /&gt;
    def testUtf8Roundtrip(self):&lt;br /&gt;
        '''check utf8 characters can go to xoxo and back'''&lt;br /&gt;
        src='Tantek \xc3\x87elik and a snowman \xe2\x98\x83'&lt;br /&gt;
        html = xoxo.toXOXO(src)&lt;br /&gt;
        self.assertEqual(src,xoxo.fromXOXO(html).encode('utf-8'))&lt;br /&gt;
    def testWindows1252Roundtrip(self):&lt;br /&gt;
        '''check 1252 characters can go to xoxo and back'''&lt;br /&gt;
        src='This is an evil\xa0space'&lt;br /&gt;
        html = xoxo.toXOXO(src)&lt;br /&gt;
        self.assertEqual(src,xoxo.fromXOXO(html).encode('windows-1252'))&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    unittest.main()&lt;br /&gt;
else:&lt;br /&gt;
    runner = unittest.TextTestRunner()&lt;br /&gt;
    suite = unittest.makeSuite(xoxoTestCases,'test')&lt;br /&gt;
    runner.run(suite)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Java =&lt;br /&gt;
== XOXOWriter.java ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Copyright 2005 Robert Sayre&lt;br /&gt;
 *&lt;br /&gt;
 * Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;);&lt;br /&gt;
 * you may not use this file except in compliance with the License.&lt;br /&gt;
 * You may obtain a copy of the License at&lt;br /&gt;
 * &lt;br /&gt;
 *      http://www.apache.org/licenses/LICENSE-2.0&lt;br /&gt;
 * &lt;br /&gt;
 * Unless required by applicable law or agreed to in writing, software&lt;br /&gt;
 * distributed under the License is distributed on an &amp;quot;AS IS&amp;quot; BASIS,&lt;br /&gt;
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&lt;br /&gt;
 * See the License for the specific language governing permissions and&lt;br /&gt;
 * limitations under the License.&lt;br /&gt;
 *&lt;br /&gt;
 * Portions of this code are derived from the Apache-licensed Python XOXO&lt;br /&gt;
 * module by Kevin Marks. &amp;lt;http://microformats.org/wiki/xoxo-sample-code&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
package org.atompub.draft.xoxo;&lt;br /&gt;
&lt;br /&gt;
import java.util.*;&lt;br /&gt;
&lt;br /&gt;
public class XOXOWriter {&lt;br /&gt;
&lt;br /&gt;
  public String[] attrs = {&amp;quot;title&amp;quot;,&amp;quot;rel&amp;quot;,&amp;quot;type&amp;quot;};&lt;br /&gt;
&lt;br /&gt;
  public String makeXOXO(List struct, String className){&lt;br /&gt;
    return makeXOXO(struct, className, 0, true);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String makeXOXO(List struct, String className,&lt;br /&gt;
                         boolean doNSDeclaration){&lt;br /&gt;
    return makeXOXO(struct, className, 0, doNSDeclaration);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String makeXOXO(List struct){&lt;br /&gt;
    return makeXOXO(struct, &amp;quot;xoxo&amp;quot;, 0, true);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String makeXOXO(Object struct, int depth){&lt;br /&gt;
    return makeXOXO(struct, null, 0, false);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String makeXOXO(Object struct, String className,&lt;br /&gt;
                         int depth, boolean doNSDeclaration){&lt;br /&gt;
    if(struct == null) return &amp;quot;&amp;quot;;&lt;br /&gt;
    StringBuffer sb = new StringBuffer();&lt;br /&gt;
    if(struct instanceof Object[]){&lt;br /&gt;
      struct = Arrays.asList((Object[]) struct);&lt;br /&gt;
    }&lt;br /&gt;
    if(struct instanceof List){&lt;br /&gt;
      sb.append(&amp;quot;&amp;lt;ol&amp;quot;);&lt;br /&gt;
      if(doNSDeclaration)&lt;br /&gt;
        sb.append(&amp;quot; xmlns=\&amp;quot;http://www.w3.org/1999/xhtml\&amp;quot;&amp;quot;);&lt;br /&gt;
      if(className != null){&lt;br /&gt;
        sb.append(&amp;quot; class=\&amp;quot;&amp;quot;);&lt;br /&gt;
        sb.append(className);&lt;br /&gt;
        sb.append(&amp;quot;\&amp;quot;&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      sb.append(&amp;quot;&amp;gt;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if(struct instanceof Map){&lt;br /&gt;
      Map d = new LinkedHashMap((Map) struct);&lt;br /&gt;
      if(d.containsKey(&amp;quot;url&amp;quot;)){&lt;br /&gt;
        sb.append(&amp;quot;&amp;lt;a href=\&amp;quot;&amp;quot; + d.get(&amp;quot;url&amp;quot;) + &amp;quot;\&amp;quot; &amp;quot;);&lt;br /&gt;
        Object text;&lt;br /&gt;
        if(d.containsKey(&amp;quot;text&amp;quot;)){&lt;br /&gt;
          text = d.get(&amp;quot;text&amp;quot;);&lt;br /&gt;
        }else if(d.containsKey(&amp;quot;title&amp;quot;)){&lt;br /&gt;
          text = d.get(&amp;quot;title&amp;quot;);&lt;br /&gt;
        }else{&lt;br /&gt;
          text = d.get(&amp;quot;url&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        for(int i=0; i&amp;lt;attrs.length; i++){&lt;br /&gt;
          String xVal = makeXOXO(d.get(attrs[i]),depth+1);&lt;br /&gt;
          if(xVal != null &amp;amp;&amp;amp; !xVal.equals(&amp;quot;&amp;quot;)){&lt;br /&gt;
            sb.append(attrs[i] + &amp;quot;=\&amp;quot;&amp;quot; + xVal + &amp;quot;\&amp;quot; &amp;quot;);&lt;br /&gt;
          }&lt;br /&gt;
          d.remove(attrs[i]);&lt;br /&gt;
        }&lt;br /&gt;
        sb.append(&amp;quot;&amp;gt;&amp;quot; + makeXOXO(text, depth+1) + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;);&lt;br /&gt;
        d.remove(&amp;quot;text&amp;quot;);&lt;br /&gt;
        d.remove(&amp;quot;url&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      if(d.size() &amp;gt; 0){&lt;br /&gt;
        sb.append(&amp;quot;&amp;lt;dl&amp;gt;&amp;quot;);&lt;br /&gt;
        for(Iterator i = d.keySet().iterator(); i.hasNext();){&lt;br /&gt;
          Object k = i.next();&lt;br /&gt;
          String ddVal = makeXOXO(d.get(k),depth+1);&lt;br /&gt;
          sb.append(&amp;quot;&amp;lt;dt&amp;gt;&amp;quot; + k + &amp;quot;&amp;lt;/dt&amp;gt;&amp;quot;);&lt;br /&gt;
          sb.append(&amp;quot;&amp;lt;dd&amp;gt;&amp;quot; + ddVal + &amp;quot;&amp;lt;/dd&amp;gt;&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        sb.append(&amp;quot;&amp;lt;/dl&amp;gt;&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
    }else if(struct instanceof List){&lt;br /&gt;
      List l = (List) struct;&lt;br /&gt;
      for(Iterator i = l.iterator(); i.hasNext();){&lt;br /&gt;
        Object item = i.next();&lt;br /&gt;
        sb.append(&amp;quot;&amp;lt;li&amp;gt;&amp;quot; + makeXOXO(item,depth+1) + &amp;quot;&amp;lt;/li&amp;gt;&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      sb.append(&amp;quot;&amp;lt;/ol&amp;gt;&amp;quot;);&lt;br /&gt;
    }else{&lt;br /&gt;
      sb.append(struct);&lt;br /&gt;
    }&lt;br /&gt;
    return sb.toString();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String toXOXO(List struct){&lt;br /&gt;
    return toXOXO(struct, false, null);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String toXOXO(Object struct){&lt;br /&gt;
    List alist = new ArrayList();&lt;br /&gt;
    alist.add(struct);&lt;br /&gt;
    return toXOXO(alist);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String toXOXO(Object struct,&lt;br /&gt;
                       boolean addHTMLWrapper,&lt;br /&gt;
                       String cssUrl){&lt;br /&gt;
    List alist = new ArrayList();&lt;br /&gt;
    alist.add(struct);&lt;br /&gt;
    return toXOXO(alist, addHTMLWrapper, cssUrl);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String toXOXO(List struct,&lt;br /&gt;
                       boolean addHTMLWrapper,&lt;br /&gt;
                       String cssUrl){&lt;br /&gt;
    String startHTML = &amp;quot;&amp;lt;!DOCTYPE html PUBLIC \&amp;quot;-//W3C//DTD&amp;quot;&lt;br /&gt;
        + &amp;quot;XHTML 1.0 Transitional//EN\n&amp;quot;&lt;br /&gt;
        + &amp;quot;http://www.w3.org/TR/xhtml1/DTD/&amp;quot;&lt;br /&gt;
        + &amp;quot;xhtml1-transitional.dtd\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
        + &amp;quot;&amp;lt;html xmlns=\&amp;quot;http://www.w3.org/1999/xhtml\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
        + &amp;quot;&amp;lt;head&amp;gt;&amp;quot;;&lt;br /&gt;
    if(addHTMLWrapper){&lt;br /&gt;
      String s = startHTML;&lt;br /&gt;
      if(cssUrl != null){&lt;br /&gt;
        s += &amp;quot;&amp;lt;style type=\&amp;quot;text/css\&amp;quot;&amp;gt;@import \&amp;quot;&amp;quot;&lt;br /&gt;
            + cssUrl + &amp;quot;\&amp;quot;;&amp;lt;/style&amp;gt;&amp;quot;;&lt;br /&gt;
      }&lt;br /&gt;
      s += &amp;quot;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;quot; + makeXOXO(struct, &amp;quot;xoxo&amp;quot;, false)&lt;br /&gt;
          + &amp;quot;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;quot;;&lt;br /&gt;
      return s;&lt;br /&gt;
    }else{&lt;br /&gt;
      return makeXOXO(struct, &amp;quot;xoxo&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XOXOParser.java ==&lt;br /&gt;
This needs some small additions to handle the XHTML DTD and named character entities.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Copyright 2005 Robert Sayre&lt;br /&gt;
 *&lt;br /&gt;
 * Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;);&lt;br /&gt;
 * you may not use this file except in compliance with the License.&lt;br /&gt;
 * You may obtain a copy of the License at&lt;br /&gt;
 * &lt;br /&gt;
 *      http://www.apache.org/licenses/LICENSE-2.0&lt;br /&gt;
 * &lt;br /&gt;
 * Unless required by applicable law or agreed to in writing, software&lt;br /&gt;
 * distributed under the License is distributed on an &amp;quot;AS IS&amp;quot; BASIS,&lt;br /&gt;
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&lt;br /&gt;
 * See the License for the specific language governing permissions and&lt;br /&gt;
 * limitations under the License.&lt;br /&gt;
 *&lt;br /&gt;
 * Portions of this code are derived from the Apache-licensed Python XOXO&lt;br /&gt;
 * module by Kevin Marks. &amp;lt;http://microformats.org/wiki/xoxo-sample-code&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
package org.atompub.draft.xoxo;&lt;br /&gt;
&lt;br /&gt;
import org.xml.sax.InputSource;&lt;br /&gt;
import org.xml.sax.SAXException;&lt;br /&gt;
import org.xml.sax.XMLReader;&lt;br /&gt;
import org.xml.sax.Attributes;&lt;br /&gt;
import org.xml.sax.helpers.XMLReaderFactory;&lt;br /&gt;
import org.xml.sax.helpers.DefaultHandler;&lt;br /&gt;
&lt;br /&gt;
import java.util.*;&lt;br /&gt;
import java.io.InputStream;&lt;br /&gt;
import java.io.StringReader;&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
&lt;br /&gt;
public class XOXOParser extends DefaultHandler {&lt;br /&gt;
&lt;br /&gt;
  protected String XHTML_NS = &amp;quot;http://www.w3.org/1999/xhtml&amp;quot;;&lt;br /&gt;
  protected List elStack;&lt;br /&gt;
  protected Map listEls;&lt;br /&gt;
  public List structs;&lt;br /&gt;
  public List xoStack;&lt;br /&gt;
  public List textStack;&lt;br /&gt;
&lt;br /&gt;
  public XOXOParser() {&lt;br /&gt;
    reset();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  protected void pushStruct(Object struct){&lt;br /&gt;
    if((struct instanceof Map) &amp;amp;&amp;amp; (((Map) struct).size() &amp;gt; 0)&lt;br /&gt;
        &amp;amp;&amp;amp; (structs.get(structs.size()-1) instanceof Map)&lt;br /&gt;
        &amp;amp;&amp;amp; (((Map) struct).containsKey(&amp;quot;url&amp;quot;))){&lt;br /&gt;
      // put back the &amp;lt;a&amp;gt;-made one for extra defs&lt;br /&gt;
      xoStack.add(structs.get(structs.size()-1));&lt;br /&gt;
    }else{&lt;br /&gt;
      structs.add(struct);&lt;br /&gt;
      xoStack.add(struct);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void startElement(String nsUri, String localName,&lt;br /&gt;
                           String qName, Attributes atts){&lt;br /&gt;
    // bounce non-XHTML elements&lt;br /&gt;
    if(nsUri.equals(XHTML_NS)){&lt;br /&gt;
      elStack.add(localName);&lt;br /&gt;
    }else{&lt;br /&gt;
      elStack.add(&amp;quot;foo&amp;quot;);&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if(localName.equals(&amp;quot;a&amp;quot;)){&lt;br /&gt;
      Map attmap = new LinkedHashMap();&lt;br /&gt;
      int len = atts.getLength();&lt;br /&gt;
      for(int i=0; i&amp;lt;len; i++){&lt;br /&gt;
        attmap.put(atts.getQName(i),atts.getValue(i));&lt;br /&gt;
      }&lt;br /&gt;
      if(attmap.containsKey(&amp;quot;href&amp;quot;)){&lt;br /&gt;
        attmap.put(&amp;quot;url&amp;quot;,attmap.get(&amp;quot;href&amp;quot;));&lt;br /&gt;
        attmap.remove(&amp;quot;href&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      pushStruct(attmap);&lt;br /&gt;
      textStack.add(&amp;quot;&amp;quot;);&lt;br /&gt;
    }else if(localName.equals(&amp;quot;dl&amp;quot;)){&lt;br /&gt;
      pushStruct(new LinkedHashMap());&lt;br /&gt;
    }else if(localName.equals(&amp;quot;ol&amp;quot;)){&lt;br /&gt;
      pushStruct(new ArrayList());&lt;br /&gt;
    }else if(localName.equals(&amp;quot;ul&amp;quot;)){&lt;br /&gt;
      pushStruct(new ArrayList());&lt;br /&gt;
    }else if(localName.equals(&amp;quot;li&amp;quot;)){&lt;br /&gt;
      textStack.add(&amp;quot;&amp;quot;);&lt;br /&gt;
    }else if(localName.equals(&amp;quot;dt&amp;quot;)){&lt;br /&gt;
      textStack.add(&amp;quot;&amp;quot;);&lt;br /&gt;
    }else if(localName.equals(&amp;quot;dd&amp;quot;)){&lt;br /&gt;
      textStack.add(&amp;quot;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void endElement(String nsUri, String localName,&lt;br /&gt;
                         String qName){&lt;br /&gt;
    elStack.remove(elStack.size()-1);&lt;br /&gt;
    // bounce non-XHTML elements&lt;br /&gt;
    if(nsUri != XHTML_NS){&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if(localName.equals(&amp;quot;a&amp;quot;)){&lt;br /&gt;
      String val = (String) textStack.remove(textStack.size()-1);&lt;br /&gt;
      if (val.length() &amp;gt; 0){&lt;br /&gt;
        Map defs = (Map) xoStack.get(xoStack.size()-1);&lt;br /&gt;
        String defVal = (String) defs.get(&amp;quot;title&amp;quot;);&lt;br /&gt;
        if((defVal != null) &amp;amp;&amp;amp; (val.equals(defVal))){&lt;br /&gt;
          val = &amp;quot;&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        defVal = (String) defs.get(&amp;quot;url&amp;quot;);&lt;br /&gt;
        if((defVal != null) &amp;amp;&amp;amp; (val.equals(defVal))){&lt;br /&gt;
          val = &amp;quot;&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        if(val.length() &amp;gt; 0){&lt;br /&gt;
          defs.put(&amp;quot;text&amp;quot;,val);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      xoStack.remove(xoStack.size()-1);&lt;br /&gt;
    }else if(localName.equals(&amp;quot;dl&amp;quot;)){&lt;br /&gt;
      xoStack.remove(xoStack.size()-1);&lt;br /&gt;
    }else if(localName.equals(&amp;quot;ol&amp;quot;)){&lt;br /&gt;
      xoStack.remove(xoStack.size()-1);&lt;br /&gt;
    }else if(localName.equals(&amp;quot;ul&amp;quot;)){&lt;br /&gt;
      xoStack.remove(xoStack.size()-1);&lt;br /&gt;
    }else if(localName.equals(&amp;quot;li&amp;quot;)){&lt;br /&gt;
      Object val = textStack.remove(textStack.size()-1);&lt;br /&gt;
      List last = (List) xoStack.get(xoStack.size()-1);&lt;br /&gt;
      if(structs.get(structs.size()-1) != last){&lt;br /&gt;
        val = structs.remove(structs.size()-1);&lt;br /&gt;
      }&lt;br /&gt;
      last.add(val);&lt;br /&gt;
    }else if(localName.equals(&amp;quot;dd&amp;quot;)){&lt;br /&gt;
      Object val = textStack.remove(textStack.size()-1);&lt;br /&gt;
      Object key = textStack.remove(textStack.size()-1);&lt;br /&gt;
      Map last = (Map) xoStack.get(xoStack.size()-1);&lt;br /&gt;
      if(structs.get(structs.size()-1) != last){&lt;br /&gt;
        val = structs.remove(structs.size()-1);&lt;br /&gt;
      }&lt;br /&gt;
      last.put(key,val);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void characters(char[] ch, int start, int length){&lt;br /&gt;
    if((xoStack.size() &amp;gt; 0)&lt;br /&gt;
        &amp;amp;&amp;amp; (!listEls.containsKey(elStack.get(elStack.size()-1)))){&lt;br /&gt;
      String text = (String) textStack.get(textStack.size()-1);&lt;br /&gt;
      String test = new String(ch,start,length);&lt;br /&gt;
      textStack.set(textStack.size()-1,text+test);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Object parse(String s) throws SAXException, IOException{&lt;br /&gt;
    return parse(new InputSource(new StringReader(s)));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Object parse(InputStream is) throws SAXException, IOException {&lt;br /&gt;
    return parse(new InputSource(is));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public Object parse(InputSource in) throws SAXException, IOException {&lt;br /&gt;
    XMLReader parser = XMLReaderFactory.createXMLReader();&lt;br /&gt;
    parser.setContentHandler(this);&lt;br /&gt;
    parser.parse(in);&lt;br /&gt;
    List returnList = new ArrayList();&lt;br /&gt;
    for(Iterator i = this.structs.iterator(); i.hasNext();){&lt;br /&gt;
      Object thing = i.next();&lt;br /&gt;
      if(thing != null){&lt;br /&gt;
        returnList.add(thing);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    while((returnList.size()==1)){&lt;br /&gt;
      if(returnList.get(0) instanceof List){&lt;br /&gt;
        returnList = (List) returnList.get(0);&lt;br /&gt;
      }else{&lt;br /&gt;
        reset();&lt;br /&gt;
        return returnList.get(0);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    reset();&lt;br /&gt;
    return returnList;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  protected void reset(){&lt;br /&gt;
    elStack = new ArrayList();&lt;br /&gt;
    listEls = new HashMap();&lt;br /&gt;
    structs = new ArrayList();&lt;br /&gt;
    xoStack = new ArrayList();&lt;br /&gt;
    textStack = new ArrayList();&lt;br /&gt;
    listEls.put(&amp;quot;ol&amp;quot;,&amp;quot;ol&amp;quot;);&lt;br /&gt;
    listEls.put(&amp;quot;ul&amp;quot;,&amp;quot;ul&amp;quot;);&lt;br /&gt;
    listEls.put(&amp;quot;dl&amp;quot;,&amp;quot;dl&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XOXOTest.java ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Copyright 2005 Robert Sayre&lt;br /&gt;
 *&lt;br /&gt;
 * Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;);&lt;br /&gt;
 * you may not use this file except in compliance with the License.&lt;br /&gt;
 * You may obtain a copy of the License at&lt;br /&gt;
 * &lt;br /&gt;
 *      http://www.apache.org/licenses/LICENSE-2.0&lt;br /&gt;
 * &lt;br /&gt;
 * Unless required by applicable law or agreed to in writing, software&lt;br /&gt;
 * distributed under the License is distributed on an &amp;quot;AS IS&amp;quot; BASIS,&lt;br /&gt;
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&lt;br /&gt;
 * See the License for the specific language governing permissions and&lt;br /&gt;
 * limitations under the License.&lt;br /&gt;
 *&lt;br /&gt;
 * Portions of this code are derived from the Apache-licensed Python XOXO&lt;br /&gt;
 * module by Kevin Marks. &amp;lt;http://microformats.org/wiki/xoxo-sample-code&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
package org.atompub.draft.xoxo.tests;&lt;br /&gt;
&lt;br /&gt;
import junit.framework.TestSuite;&lt;br /&gt;
import junit.framework.TestCase;&lt;br /&gt;
import junit.textui.TestRunner;&lt;br /&gt;
import org.atompub.draft.xoxo.XOXOWriter;&lt;br /&gt;
import org.atompub.draft.xoxo.XOXOParser;&lt;br /&gt;
&lt;br /&gt;
import java.util.*;&lt;br /&gt;
&lt;br /&gt;
public class XOXOTest extends TestCase {&lt;br /&gt;
&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    new TestRunner().doRun(new TestSuite(XOXOTest.class));&lt;br /&gt;
  }&lt;br /&gt;
  String XHTML_DEC = &amp;quot;xmlns=\&amp;quot;http://www.w3.org/1999/xhtml\&amp;quot; &amp;quot;;&lt;br /&gt;
  public String simpleListHTML = &amp;quot;&amp;lt;ol &amp;quot;&lt;br /&gt;
  + XHTML_DEC&lt;br /&gt;
  + &amp;quot;class=\&amp;quot;xoxo\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
  + &amp;quot;&amp;lt;li&amp;gt;1&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;2&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;3&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public void testSimpleList(){&lt;br /&gt;
    String [] numbers = {&amp;quot;1&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;};&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    assertEquals(simpleListHTML,&lt;br /&gt;
                 xoxo.toXOXO(Arrays.asList(numbers)));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testStringIntegerList(){&lt;br /&gt;
    Object[] numbers = {new Integer(1),&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;};&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    assertEquals(simpleListHTML,&lt;br /&gt;
                 xoxo.toXOXO(Arrays.asList(numbers)));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String nestedListHTML = &amp;quot;&amp;lt;ol &amp;quot;&lt;br /&gt;
  + XHTML_DEC&lt;br /&gt;
  + &amp;quot;class=\&amp;quot;xoxo\&amp;quot;&amp;gt;&amp;lt;li&amp;gt;1&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&amp;quot;&lt;br /&gt;
  + &amp;quot;&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;2&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;3&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public void testNestedList(){&lt;br /&gt;
    Object[] arr = {&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;};&lt;br /&gt;
    Object[] nested = {&amp;quot;1&amp;quot;,Arrays.asList(arr)};&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    assertEquals(nestedListHTML,&lt;br /&gt;
                 xoxo.toXOXO(Arrays.asList(nested)));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testNestedArray(){&lt;br /&gt;
    Object[] arr = {&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;};&lt;br /&gt;
    Object[] nested = {&amp;quot;1&amp;quot;,arr};&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    assertEquals(nestedListHTML,&lt;br /&gt;
                 xoxo.toXOXO(Arrays.asList(nested)));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String dictHTML = &amp;quot;&amp;lt;ol &amp;quot;&lt;br /&gt;
  + XHTML_DEC&lt;br /&gt;
  + &amp;quot;class=\&amp;quot;xoxo\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
  + &amp;quot;&amp;lt;li&amp;gt;&amp;lt;dl&amp;gt;&amp;lt;dt&amp;gt;test&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;1&amp;lt;/dd&amp;gt;&amp;lt;dt&amp;gt;name&amp;lt;/dt&amp;gt;&amp;quot;&lt;br /&gt;
  + &amp;quot;&amp;lt;dd&amp;gt;Kevin&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public void testDictionary(){&lt;br /&gt;
    Map dict = new LinkedHashMap();&lt;br /&gt;
    dict.put(&amp;quot;test&amp;quot;, new Integer(1));&lt;br /&gt;
    dict.put(&amp;quot;name&amp;quot;, &amp;quot;Kevin&amp;quot;);&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    assertEquals(dictHTML,&lt;br /&gt;
                 xoxo.toXOXO(dict));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String singleHTML = &amp;quot;&amp;lt;ol &amp;quot;&lt;br /&gt;
  + XHTML_DEC&lt;br /&gt;
  + &amp;quot;class=\&amp;quot;xoxo\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
  + &amp;quot;&amp;lt;li&amp;gt;test&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public void testSingleItem(){&lt;br /&gt;
    String item = &amp;quot;test&amp;quot;;&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    assertEquals(singleHTML,&lt;br /&gt;
                 xoxo.toXOXO(item));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testWrapDiffers(){&lt;br /&gt;
    String item = &amp;quot;test&amp;quot;;&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    String nowrap = xoxo.toXOXO(item);&lt;br /&gt;
    Object[] itemArr = {item};&lt;br /&gt;
    String wrap = xoxo.toXOXO(Arrays.asList(itemArr),true,null);&lt;br /&gt;
    assertFalse(wrap.equals(nowrap));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  String startHTML = &amp;quot;&amp;lt;!DOCTYPE html PUBLIC \&amp;quot;-//W3C//DTD&amp;quot;&lt;br /&gt;
        + &amp;quot;XHTML 1.0 Transitional//EN\n&amp;quot;&lt;br /&gt;
        + &amp;quot;http://www.w3.org/TR/xhtml1/DTD/&amp;quot;&lt;br /&gt;
        + &amp;quot;xhtml1-transitional.dtd\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
        + &amp;quot;&amp;lt;html xmlns=\&amp;quot;http://www.w3.org/1999/xhtml\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
        + &amp;quot;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;quot;;&lt;br /&gt;
  public String singleWrapHTML = &amp;quot;&amp;lt;ol &amp;quot;&lt;br /&gt;
  + &amp;quot;class=\&amp;quot;xoxo\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
  + &amp;quot;&amp;lt;li&amp;gt;test&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;quot;;&lt;br /&gt;
  public String endHTML = &amp;quot;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public void testWrapSingleItem(){&lt;br /&gt;
    String item = &amp;quot;test&amp;quot;;&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    assertEquals(startHTML + singleWrapHTML + endHTML,&lt;br /&gt;
                 xoxo.toXOXO(item,true,null));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testXOXOParser(){&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    try{&lt;br /&gt;
      parser.parse(dictHTML);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testDictRoundTrip(){&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    Map dict = new LinkedHashMap();&lt;br /&gt;
    dict.put(&amp;quot;test&amp;quot;, &amp;quot;1&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;name&amp;quot;, &amp;quot;Kevin&amp;quot;);&lt;br /&gt;
    String html = xoxo.toXOXO(dict);&lt;br /&gt;
     try{&lt;br /&gt;
      Object newDict = parser.parse(html);&lt;br /&gt;
      assertEquals(dict,newDict);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testListRoundTrip(){&lt;br /&gt;
    Object[] obj = {&amp;quot;1&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;};&lt;br /&gt;
    List testList = Arrays.asList(obj);&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    String html = xoxo.toXOXO(testList);&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    try{&lt;br /&gt;
      Object newList = parser.parse(html);&lt;br /&gt;
      assertEquals(testList,newList);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testListOfDictsRoundTrip(){&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    Map dict = new LinkedHashMap();&lt;br /&gt;
    dict.put(&amp;quot;test&amp;quot;, &amp;quot;1&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;name&amp;quot;, &amp;quot;Kevin&amp;quot;);&lt;br /&gt;
    Map dict2 = new LinkedHashMap();&lt;br /&gt;
    dict2.put(&amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;);&lt;br /&gt;
    dict2.put(&amp;quot;three&amp;quot;, &amp;quot;four&amp;quot;);&lt;br /&gt;
    dict2.put(&amp;quot;five&amp;quot;, &amp;quot;six&amp;quot;);&lt;br /&gt;
    Object[] obj = {&amp;quot;1&amp;quot;,dict,dict2};&lt;br /&gt;
    List testList = Arrays.asList(obj);&lt;br /&gt;
    String html = xoxo.toXOXO(testList);&lt;br /&gt;
    try{&lt;br /&gt;
      Object newList = parser.parse(html);&lt;br /&gt;
      assertEquals(testList,newList);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testListOfListsRoundTrip(){&lt;br /&gt;
    Object[] list1 = {&amp;quot;1&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;};&lt;br /&gt;
    Object[] list2 = {&amp;quot;4&amp;quot;,&amp;quot;5&amp;quot;,&amp;quot;6&amp;quot;, Arrays.asList(list1)};&lt;br /&gt;
    Object[] list3 = {&amp;quot;7&amp;quot;, Arrays.asList(list2)};&lt;br /&gt;
    Object[] list4 = {&amp;quot;8&amp;quot;, Arrays.asList(list3)};&lt;br /&gt;
    List testList = Arrays.asList(list4);&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    String html = xoxo.toXOXO(testList);&lt;br /&gt;
    try{&lt;br /&gt;
      Object newList = parser.parse(html);&lt;br /&gt;
      assertEquals(testList,newList);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testDictOfListsRoundTrip(){&lt;br /&gt;
    Object[] list1 = {&amp;quot;1&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;};&lt;br /&gt;
    Object[] list2 = {&amp;quot;4&amp;quot;,&amp;quot;5&amp;quot;,&amp;quot;6&amp;quot;};&lt;br /&gt;
    Object[] list3 = {&amp;quot;7&amp;quot;};&lt;br /&gt;
    Object[] list4 = {&amp;quot;8&amp;quot;, &amp;quot;9&amp;quot;};&lt;br /&gt;
    Map dict = new LinkedHashMap();&lt;br /&gt;
    dict.put(&amp;quot;foo&amp;quot;, Arrays.asList(list1));&lt;br /&gt;
    dict.put(&amp;quot;bar&amp;quot;, Arrays.asList(list2));&lt;br /&gt;
    dict.put(&amp;quot;baz&amp;quot;, Arrays.asList(list3));&lt;br /&gt;
    dict.put(&amp;quot;qux&amp;quot;, Arrays.asList(list4));&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    String html = xoxo.toXOXO(dict);&lt;br /&gt;
    try{&lt;br /&gt;
      Object newDict = parser.parse(html);&lt;br /&gt;
      assertEquals(dict,newDict);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String junkXOXO = &amp;quot;&amp;lt;ol &amp;quot;&lt;br /&gt;
  + XHTML_DEC&lt;br /&gt;
  + &amp;quot;class=\&amp;quot;xoxo\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
  + &amp;quot;bad&amp;lt;li&amp;gt;&amp;lt;dl&amp;gt;worse&amp;lt;dt&amp;gt;good&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;buy&amp;lt;/dd&amp;gt; now&amp;lt;/dl&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public void testXOXOJunkInContainers(){&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    Map dict = new LinkedHashMap();&lt;br /&gt;
    dict.put(&amp;quot;good&amp;quot;,&amp;quot;buy&amp;quot;);&lt;br /&gt;
    try{&lt;br /&gt;
      Object newDict = parser.parse(junkXOXO);&lt;br /&gt;
      assertEquals(dict,newDict);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String junkElementXOXO = &amp;quot;&amp;lt;ol &amp;quot;&lt;br /&gt;
  + XHTML_DEC&lt;br /&gt;
  + &amp;quot;&amp;gt;&amp;lt;li&amp;gt;bad&amp;lt;dl&amp;gt;&amp;lt;dt&amp;gt;good&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;buy&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&amp;quot;&lt;br /&gt;
  + &amp;quot;worse&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;bag&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;OK&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;fish&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public void testXOXOjunkInElements(){&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    Map dict = new LinkedHashMap();&lt;br /&gt;
    dict.put(&amp;quot;good&amp;quot;,&amp;quot;buy&amp;quot;);&lt;br /&gt;
    Object[] ok = {&amp;quot;OK&amp;quot;};&lt;br /&gt;
    Object[] obj ={dict, Arrays.asList(ok)};&lt;br /&gt;
    List testList = Arrays.asList(obj);&lt;br /&gt;
    try{&lt;br /&gt;
      Object newList = parser.parse(junkElementXOXO);&lt;br /&gt;
      assertEquals(testList,newList);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String xoxoSpacesNewlines = &amp;quot;&amp;lt;ol &amp;quot; +  XHTML_DEC +&lt;br /&gt;
      &amp;quot; class='xoxo'&amp;gt; \n&amp;quot; +&lt;br /&gt;
      &amp;quot;  &amp;lt;li&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;    &amp;lt;dl&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dt&amp;gt;text&amp;lt;/dt&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dd&amp;gt;item 1&amp;lt;/dd&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dt&amp;gt;description&amp;lt;/dt&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dd&amp;gt; This item represents the main&amp;quot; +&lt;br /&gt;
      &amp;quot; point we're trying to make.&amp;lt;/dd&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dt&amp;gt;url&amp;lt;/dt&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dd&amp;gt;http://example.com/more.xoxo&amp;lt;/dd&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dt&amp;gt;title&amp;lt;/dt&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dd&amp;gt;title of item 1&amp;lt;/dd&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dt&amp;gt;type&amp;lt;/dt&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dd&amp;gt;text/xml&amp;lt;/dd&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dt&amp;gt;rel&amp;lt;/dt&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dd&amp;gt;help&amp;lt;/dd&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;    &amp;lt;/dl&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;  &amp;lt;/li&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;&amp;lt;/ol&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public void testXOXOWithSpacesAndNewlines(){&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    Map dict = new LinkedHashMap();&lt;br /&gt;
    dict.put(&amp;quot;text&amp;quot;,&amp;quot;item 1&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;description&amp;quot;,&amp;quot; This item represents the main&amp;quot; +&lt;br /&gt;
        &amp;quot; point we're trying to make.&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;url&amp;quot;,&amp;quot;http://example.com/more.xoxo&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;title&amp;quot;,&amp;quot;title of item 1&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;type&amp;quot;,&amp;quot;text/xml&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;rel&amp;quot;,&amp;quot;help&amp;quot;);&lt;br /&gt;
    try{&lt;br /&gt;
      Object newDict = parser.parse(xoxoSpacesNewlines);&lt;br /&gt;
      assertEquals(dict,newDict);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String xoxoSample = &amp;quot;&amp;lt;ol &amp;quot; +  XHTML_DEC +&lt;br /&gt;
      &amp;quot; class='xoxo'&amp;gt; \n&amp;quot; +&lt;br /&gt;
      &amp;quot;  &amp;lt;li&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;    &amp;lt;dl&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dt&amp;gt;text&amp;lt;/dt&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dd&amp;gt;item 1&amp;lt;/dd&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dt&amp;gt;url&amp;lt;/dt&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dd&amp;gt;http://example.com/more.xoxo&amp;lt;/dd&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dt&amp;gt;title&amp;lt;/dt&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dd&amp;gt;title of item 1&amp;lt;/dd&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dt&amp;gt;type&amp;lt;/dt&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dd&amp;gt;text/xml&amp;lt;/dd&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dt&amp;gt;rel&amp;lt;/dt&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;        &amp;lt;dd&amp;gt;help&amp;lt;/dd&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;    &amp;lt;/dl&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;  &amp;lt;/li&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;&amp;lt;/ol&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public String smartXOXOSample = &amp;quot;&amp;lt;ol &amp;quot; + XHTML_DEC +&lt;br /&gt;
      &amp;quot;class=\&amp;quot;xoxo\&amp;quot;&amp;gt; \n&amp;quot; +&lt;br /&gt;
      &amp;quot;  &amp;lt;li&amp;gt;&amp;lt;a href=\&amp;quot;http://example.com/more.xoxo\&amp;quot;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;         title=\&amp;quot;title of item 1\&amp;quot;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;         type=\&amp;quot;text/xml\&amp;quot;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;         rel=\&amp;quot;help\&amp;quot;&amp;gt;item 1&amp;lt;/a&amp;gt; \n&amp;quot; +&lt;br /&gt;
      &amp;quot;&amp;lt;!-- note how the \&amp;quot;text\&amp;quot; property is simply&amp;quot; +&lt;br /&gt;
      &amp;quot; the contents of the &amp;lt;a&amp;gt; element --&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;  &amp;lt;/li&amp;gt;\n&amp;quot; +&lt;br /&gt;
      &amp;quot;&amp;lt;/ol&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public void testSpecialAttributeDecoding(){&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    try{&lt;br /&gt;
      Object xoxoDict = parser.parse(xoxoSample);&lt;br /&gt;
      Object xoxoDict2 = parser.parse(smartXOXOSample);&lt;br /&gt;
      assertEquals(xoxoDict,xoxoDict2);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String specialAttrHTML =  &amp;quot;&amp;lt;ol &amp;quot; + XHTML_DEC +&lt;br /&gt;
      &amp;quot;class=\&amp;quot;xoxo\&amp;quot;&amp;gt;&amp;quot; +&lt;br /&gt;
      &amp;quot;&amp;lt;li&amp;gt;&amp;lt;a href=\&amp;quot;http://example.com/more.xoxo\&amp;quot; title=\&amp;quot;sample url\&amp;quot; &amp;quot; +&lt;br /&gt;
      &amp;quot;rel=\&amp;quot;help\&amp;quot; type=\&amp;quot;text/xml\&amp;quot; &amp;gt;an example&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  public void testSpecialAttributeEncode(){&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    Map dict = new LinkedHashMap();&lt;br /&gt;
    dict.put(&amp;quot;url&amp;quot;,&amp;quot;http://example.com/more.xoxo&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;title&amp;quot;,&amp;quot;sample url&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;type&amp;quot;,&amp;quot;text/xml&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;rel&amp;quot;,&amp;quot;help&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;text&amp;quot;,&amp;quot;an example&amp;quot;);&lt;br /&gt;
    String html = xoxo.toXOXO(dict);&lt;br /&gt;
    assertEquals(specialAttrHTML,html);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testSpecialAttributeRoundTripFull(){&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    Map dict = new LinkedHashMap();&lt;br /&gt;
    dict.put(&amp;quot;url&amp;quot;,&amp;quot;http://example.com/more.xoxo&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;title&amp;quot;,&amp;quot;sample url&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;type&amp;quot;,&amp;quot;text/xml&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;rel&amp;quot;,&amp;quot;help&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;text&amp;quot;,&amp;quot;an example&amp;quot;);&lt;br /&gt;
    String html = xoxo.toXOXO(dict);&lt;br /&gt;
    try{&lt;br /&gt;
      Object newDict = parser.parse(html);&lt;br /&gt;
      assertEquals(dict,newDict);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testSpecialAttributeRoundTripNoText(){&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    Map dict = new LinkedHashMap();&lt;br /&gt;
    dict.put(&amp;quot;url&amp;quot;,&amp;quot;http://example.com/more.xoxo&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;title&amp;quot;,&amp;quot;sample url&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;type&amp;quot;,&amp;quot;text/xml&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;rel&amp;quot;,&amp;quot;help&amp;quot;);&lt;br /&gt;
    String html = xoxo.toXOXO(dict);&lt;br /&gt;
    try{&lt;br /&gt;
      Object newDict = parser.parse(html);&lt;br /&gt;
      assertEquals(dict,newDict);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testSpecialAttributeRoundTripNoTextOrTitle(){&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    Map dict = new LinkedHashMap();&lt;br /&gt;
    dict.put(&amp;quot;url&amp;quot;,&amp;quot;http://example.com/more.xoxo&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;type&amp;quot;,&amp;quot;text/xml&amp;quot;);&lt;br /&gt;
    dict.put(&amp;quot;rel&amp;quot;,&amp;quot;help&amp;quot;);&lt;br /&gt;
    String html = xoxo.toXOXO(dict);&lt;br /&gt;
    try{&lt;br /&gt;
      Object newDict = parser.parse(html);&lt;br /&gt;
      assertEquals(dict,newDict);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void testUnicodeRoundTrip(){&lt;br /&gt;
    String s = &amp;quot;Tantek Çelik and a snowman ?&amp;quot;;&lt;br /&gt;
    XOXOWriter xoxo = new XOXOWriter();&lt;br /&gt;
    XOXOParser parser = new XOXOParser();&lt;br /&gt;
    String html = xoxo.toXOXO(s);&lt;br /&gt;
    try{&lt;br /&gt;
      Object newString = parser.parse(html);&lt;br /&gt;
      assertEquals(s,newString);&lt;br /&gt;
    }catch (Exception e){&lt;br /&gt;
      fail(e.getMessage());&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div  style=&amp;quot;display:none&amp;quot;&amp;gt;&lt;br /&gt;
[l_sp]&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://test.com&amp;quot;&amp;gt; test&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>1143297912</name></author>
	</entry>
	<entry>
		<id>https://microformats.org/wiki/index.php?title=xfolk-scuttle&amp;diff=5563</id>
		<title>xfolk-scuttle</title>
		<link rel="alternate" type="text/html" href="https://microformats.org/wiki/index.php?title=xfolk-scuttle&amp;diff=5563"/>
		<updated>2006-03-25T14:41:27Z</updated>

		<summary type="html">&lt;p&gt;1143297912: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Scuttle =&lt;br /&gt;
&amp;lt;p&amp;gt;An issue with scuttle's xhtml presentation is that it specifies a collection of bookmarks with the implicit idea that bookmarks are separated each time a new URL is specfied in a &amp;amp;lt;dt&amp;gt; element.  Further, things like tags are specified as a collection in a sublist.  This approach is fine if one expects that the information will always be presented in a definition list.  Such will not be the general case for those not already using scuttle.&amp;lt;/p&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;div id=&amp;quot;bookmarks&amp;quot;&amp;amp;gt;&lt;br /&gt;
  &amp;amp;lt;h2&amp;amp;gt;Your Bookmarks&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
  &amp;amp;lt;dl&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;dt&amp;amp;gt;&lt;br /&gt;
      &amp;amp;lt;a href=&amp;quot;http://www.sifry.com/alerts/archives/000306.html&amp;quot;&amp;amp;gt;&lt;br /&gt;
        Sifry&amp;amp;amp;#039;s Alerts: Technorati launches Related Tags&lt;br /&gt;
      &amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;/dt&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;dd class=&amp;quot;description&amp;quot;&amp;amp;gt;&lt;br /&gt;
      Ever wanted to see what posts are related to other posts, what &lt;br /&gt;
      tags are related to others? Now you can! Just check under the &lt;br /&gt;
      Tag description on most tag pages, like this one, or this one, &lt;br /&gt;
      and you&amp;amp;amp;#039;ll see the patterns. Can you smell the emergence?&lt;br /&gt;
    &amp;amp;lt;/dd&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;dd class=&amp;quot;tags&amp;quot;&amp;amp;gt;&lt;br /&gt;
      2005-04-09 to &lt;br /&gt;
      &amp;amp;lt;a href=&amp;quot;http://www.niallkennedy.com/scuttle/bookmarks.php/budgibson/folksonomy&amp;quot;&amp;amp;gt;&lt;br /&gt;
        folksonomy&lt;br /&gt;
      &amp;amp;lt;/a&amp;amp;gt;, &lt;br /&gt;
      &amp;amp;lt;a href=&amp;quot;http://www.niallkennedy.com/scuttle/bookmarks.php/budgibson/technorati&amp;quot;&amp;amp;gt;&lt;br /&gt;
        technorati&lt;br /&gt;
      &amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;/dd&amp;amp;gt;&lt;br /&gt;
  &amp;amp;lt;/dl&amp;amp;gt;&lt;br /&gt;
&amp;amp;lt;/div&amp;amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;To get this into xFolk 0.5, the easiest way is to have each xFolk entry in its own &amp;amp;lt;dl&amp;gt; element of class xfolkentry so that individual xFolk entries can be demarcated.  We will also have to add class attributes in cases where there are none.  Changed and added components are marked with comments at the end of the line.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;div id=&amp;quot;bookmarks&amp;quot;&amp;amp;gt;&lt;br /&gt;
  &amp;amp;lt;h2&amp;amp;gt;Your Bookmarks&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
  &amp;amp;lt;dl class=&amp;quot;xfolkentry&amp;quot;&amp;amp;gt; &amp;lt;!-- changed --&amp;gt;&lt;br /&gt;
    &amp;amp;lt;dt&amp;amp;gt;&lt;br /&gt;
      &amp;amp;lt;a class=&amp;quot;taggedlink&amp;quot; &amp;lt;!-- changed --&amp;gt;&lt;br /&gt;
      href=&amp;quot;http://www.sifry.com/alerts/archives/000306.html&amp;quot;&amp;amp;gt;&lt;br /&gt;
        Sifry&amp;amp;amp;#039;s Alerts: Technorati launches Related Tags&lt;br /&gt;
      &amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;/dt&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;dd class=&amp;quot;description&amp;quot;&amp;amp;gt; &amp;lt;!-- not changed because works with xFolk --&amp;gt;&lt;br /&gt;
      Ever wanted to see what posts are related to other posts, what &lt;br /&gt;
      tags are related to others? Now you can! Just check under the &lt;br /&gt;
      Tag description on most tag pages, like this one, or this one, &lt;br /&gt;
      and you&amp;amp;amp;#039;ll see the patterns. Can you smell the emergence?&lt;br /&gt;
    &amp;amp;lt;/dd&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;dd class=&amp;quot;tags&amp;quot;&amp;amp;gt;&lt;br /&gt;
      2005-04-09 to &lt;br /&gt;
      &amp;amp;lt;a rel=&amp;quot;tag&amp;quot; &lt;br /&gt;
       href=&amp;quot;http://www.niallkennedy.com/scuttle/bookmarks.php/budgibson/folksonomy&amp;quot;&amp;amp;gt; &amp;lt;!-- changed --&amp;gt;&lt;br /&gt;
        folksonomy&lt;br /&gt;
      &amp;amp;lt;/a&amp;amp;gt;, &lt;br /&gt;
      &amp;amp;lt;a rel=&amp;quot;tag&amp;quot; &lt;br /&gt;
       href=&amp;quot;http://www.niallkennedy.com/scuttle/bookmarks.php/budgibson/technorati&amp;quot;&amp;amp;gt; &amp;lt;!-- changed --&amp;gt;&lt;br /&gt;
        technorati&lt;br /&gt;
      &amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
    &amp;amp;lt;/dd&amp;amp;gt;&lt;br /&gt;
  &amp;amp;lt;/dl&amp;amp;gt;&lt;br /&gt;
&amp;amp;lt;/div&amp;amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div  style=&amp;quot;display:none&amp;quot;&amp;gt;&lt;br /&gt;
[l_sp]&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://test.com&amp;quot;&amp;gt; test&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>1143297912</name></author>
	</entry>
	<entry>
		<id>https://microformats.org/wiki/index.php?title=use&amp;diff=5562</id>
		<title>use</title>
		<link rel="alternate" type="text/html" href="https://microformats.org/wiki/index.php?title=use&amp;diff=5562"/>
		<updated>2006-03-25T14:41:18Z</updated>

		<summary type="html">&lt;p&gt;1143297912: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= So you wanna use microformats? =&lt;br /&gt;
&lt;br /&gt;
Microformats are designed to be similar to current markup styles. This means that it is quite possible that you won't have to do much work to produce microformats on your site. Many common kinds of content can be marked up in microformats. Chances are, you already have some of them on your site. Start with the obvious ones. For example... &lt;br /&gt;
&lt;br /&gt;
* Do you have events information on your site? Then mark those events up with [[hCalendar]]. &lt;br /&gt;
** Start with the [http://microformats.org/code/hcalendar/creator hCalendar creator]. &lt;br /&gt;
* Do you have people, organizations, or contact information? Then mark those up with [[hCard]].&lt;br /&gt;
** Start with the [http://microformats.org/code/hcard/creator hCard creator] and take a look at the [[hcard-examples]].&lt;br /&gt;
** Read [[hcard-authoring]] for tips and guidelines on how to best markup existing content with hCard.&lt;br /&gt;
* Do you have an explicit copyright license on your content? Then markup the link to your license with [[rel-license]]. &lt;br /&gt;
* Do you publish social network / relationship info? Then mark that up with [http://gmpg.org/xfn/ XFN]. &lt;br /&gt;
* Are you tagging things? Then use [[rel-tag]] (for your own stuff) or [[xFolk]] (for tagging any URL).&lt;br /&gt;
* Are you publishing lists or outlines? Then use [[XOXO]]. &lt;br /&gt;
* Do you publish reviews? Then use [[hReview]].&lt;br /&gt;
** Start with the [http://microformats.org/code/hreview/creator hReview creator]. &lt;br /&gt;
* Do you publish press releases? Then use [[hatom|hAtom]].&lt;br /&gt;
&lt;br /&gt;
And here's a few more tips:&lt;br /&gt;
&lt;br /&gt;
* Try to produce clean, semantic xhtml. Often this will get you very close to microformats on its own.&lt;br /&gt;
** [http://tantek.com/log/2004/07.html#classmeaningnotshow Class for meaning not for show]&lt;br /&gt;
** http://microformats.org/wiki/SemanticXHTMLDesignPrinciples&lt;br /&gt;
** [http://tantek.com/presentations/20040928sdforumws/semantic-xhtml.html Semantic XHTML]&lt;br /&gt;
** [http://tantek.com/presentations/2005/03/elementsofxhtml Meaningful XHTML]&lt;br /&gt;
** [http://www.tantek.com/presentations/2004etech/realworldsemanticspres.html Real World Semantics]&lt;br /&gt;
** ''need more links here'' --[[User:RyanKing|RyanKing]] 14:42, 17 Jan 2006 (PST)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div  style=&amp;quot;display:none&amp;quot;&amp;gt;&lt;br /&gt;
[l_sp]&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://test.com&amp;quot;&amp;gt; test&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>1143297912</name></author>
	</entry>
</feed>