The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

XMLNews::HTMLTemplate - A module for converting NITF to HTML.

SYNOPSIS

use XMLNews::HTMLTemplate;

my $template = new XMLNews::HTMLTemplate();
$template->readTemplate("mytemplate.html");

$template->applyTemplate("output.html", "story.xml", "story.rdf");

DESCRIPTION

NOTE: this module requires the XML::Parser and XMLNews::Meta modules.

WARNING: this module is not thread-safe or re-entrant.

The XMLNews::HTMLTemplate module provides a simple mechanism for creating HTML pages from XML/NITF news stories and/or XML/RDF metadata files based on a user-supplied template file. The template is a simple HTML file (SGML or XML flavour) using special template commands, which the user includes as processing instructions, as in the following example:

<h1><?XNews insert headline?></h1>

To create an HTML page, you must first create an empty HTMLTemplate object:

my $template = new XMLNews::HTMLTemplate();

Next, you load the HTML template into the object:

$template->readTemplate("mytemplate.html");

Now, you can apply the same compiled template object repeatedly to different XML/NITF and/or XML/RDF documents to generate HTML pages:

$template->applyTemplate("outfile.html", "newsstory.xml", "newsstory.rdf");

In this example, the module will read the XML/NITF news story in newstory.xml and the XML/RDF metadata in newstory.rdf, and write an HTML page at outfile.html.

METHODS

new ()

Construct a new, empty instance of an XMLNews::HTMLTemplate object:

my $template = new XMLNews::HTMLTemplate();
readTemplate(TEMPLATE)

Compile a template file into the current object, discarding any existing compiled template:

$template->readTemplate("news-template.htm");

The TEMPLATE argument may be either a string containing a file name or an IO::Handle object.

You must compile a template before you can use it, but once you have compiled the template, you may use it to create many different HTML pages.

applyTemplate(OUT_FILE, NITF_FILE, RDF_FILE)

Apply the compiled template to an NITF-format news story and/or and RDF-format metadata file, filling in the fields in the template commands using the properties found in these files:

$template->applyTemplate("story999.html", "story999.xml", "story999.rdf");

The three arguments may be either strings containing file names or IO::Handle objects. If the file specified by OUT_FILE already exists, this method will overwrite its contents.

Either or both of the NITF_FILE or the RDF_FILE parameters may be omitted if desired.

HTML TEMPLATE FORMAT

An XMLNews template file is an HTML file containing special processing instructions, beginning with "<?XNews " and ending with ">" or "?>". Following the word "XNews", each processing instruction contains whitespace and a command word, followed optionally by command parameters, as in the following example:

<?XNews insert headline?>

Typically, the template would include this processing instruction within an HTML element:

<h1><?XNews insert headline?></h1>

All processing instructions beginning with characters other than "XNews" will be ignored and passed through as-is (they may be used for other sorts of processing).

Template Commands

Any of the following six command words may follow the word "XNews" in a processing instruction (all commands are case-sensitive):

namespace PREFIX=URI

Declare a prefix representing a namespace:

<?XNews namespace xn=http://www.xmlnews.org/namespaces/meta#?>

Once the prefix is declared, you can use it to point to properties in the RDF file:

<?XNews insert xn:person?>

Note that it is the namespace URIs rather than the prefixes that are matched against RDF; the following would work identically with the same RDF file:

<?XNews namespace aBcDe=http://www.xmlnews.org/namespaces/meta#?>
<?XNews insert aBcDe:person?>

All namespace declarations have global scope from the point of declaration forward; it is usually best to include all of the declarations at the top of the template.

insert PROPERTY

Insert the value of PROPERTY at this point in the generated document:

<?XNews insert dateline?>

If there is more than one value available for the property, all of the values will be inserted in random order, separated by spaces, unless this processing instruction occurs within a "foreach" block (see below).

if PROPERTY

Begin a conditional statement:

<?XNews if byline?>
 <h2><?XNews insert byline?></h2>
<?XNews end?>

Everything between this processing instruction and the matching "end" instruction will be included only if [property] has a non-null value.

"if" commands may be nested.

else

Specify the default action for when an "if" command fails:

<?XNews if date?>
 <p>Date: <?XNews insert date?></p>
<?XNews else?>
 <p>Undated.</p>
<?XNews end?>
foreach PROPERTY

Iterate over multiple values for a property:

<?XNews foreach http://www.inews.org/props/CompanyCode?>
<p>Ticker: <?XNews insert http://www.inews.org/props/CompanyCode?></p>
<?XNews end?>

These instructions will create a separate <p> element for every CompanyCode (ticker) value available.

end

Terminate an "if" or "foreach" statement:

<?XNews if dateline?>
<p>Dateline: <?XNews insert dateline?></p>
<?XNews end?>

Property Names

Property names consist of two parts: a namespace and a base name. Properties derived from the NITF document have null namespace parts; properties derived from the RDF metadata have non-null namespace parts. To specify a property with a non-null namespace part, you must first declare a namespace prefix, and then include the prefix before the property name separated with a colon:

<?XNews namespace xn=http://www.xmlnews.org/namespaces/meta#?>

<?XNews insert xn:companyCode?>

These commands insert the value of the property "companyCode" in the http://www.xmlnews.org/namespaces/meta# namespace, as found in the RDF metadata file. You may access any property specified in the news story's RDF metadata file in this way (such as ticker symbols, dates, and the language of the resource).

In addition to the metadata properties in the RDF file, there are nine special pseudo-properties that have a NULL namespace (most of these duplicate properties in the RDF, but their values are also given in the news story):

headline
The text of the story's headline, if any.
subheadline
The text of the story's subheadline(s), if any.  There may be more
than one value for this property, so it is best to include it in a
"foreach" block.
byline
The text of the story's byline(s), if any.  There may be more than
one value for this property, so it is best to include it in a
"foreach" block.
distributor
The text of the distributor's name, if any.
dateline
The text of the story's dateline, if any.
series.name
The name of the series to which this story belongs, if any.
series.part
The position of this story in a series, if any.
series.totalpart
The total number of stories in this series, if any.
body
HTML markup for the body of the story, divided into paragraphs.

Sample Template

Here is a simple sample template for a news story (using XML/HTML syntax); it does not use any RDF properties:

<?xml version="1.0"?>

<html>
<head>
<title>News Story: <?XNews insert headline?></title>
</head>
<body>
<h1><?XNews insert headline?></h1>

<?XNews foreach subheadline?>
<h2><?XNews insert subheadline?></h2>
<?XNews end?>

<?XNews foreach byline?>
<p><em><?XNews insert byline?></em></p>
<?XNews end?>

<p>(Dateline: <?XNews insert dateline?>)</p>

<?XNews insert body?>

</body>
</html>

CONFORMANCE NOTE

The processing instruction target is "XNews" rather than XMLNews so that template files can be well-formed XML if desired (XML reserves all processing-instruction targets beginning with [xX][mM][lL]).

Given the wide variations in common HTML usage, this module uses pattern matching on the HTML templates rather than trying to parse them as SGML or XML documents. As a result, it will recognise template commands even within comments and attribute values, places where they are not properly recognised in SGML or XML.

AUTHOR

This module was originally written by David Megginson (david@megginson.com).