Home > Archive > PERL Modules > March 2004 > [RFC] New module FrameMaker::MifTree
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
[RFC] New module FrameMaker::MifTree
|
|
| Roel van der Steen 2004-03-19, 12:55 pm |
| Hi all
I've written a new module FrameMaker::MifTree that I'm planning to put
on CPAN. Please take a look at the documentation and tell me what you
think.
Also, I'm not sure if FrameMaker::MifTree is the right module name.
There used to be a module FrameMaker::MIF which served the same
purpose. I'm also prepared to stick the module under "Tree::",
"Parse::" or "Text::". Please advise.
Thanks
Roel van der Steen
--
DSLIP: adpOp
--
NAME
Local::MifTree - A MIF Parser
VERSION
This document describes version 0.043, released 4 February
2004.
SYNOPSIS
use Local::MifTree;
my $mif = Local::MifTree->new;
$mif->parse_miffile('filename.mif');
@strings = $mif->daughters_by_name("String");
print $strings[0]->string;
$strings[3]->string("Just another new string.");
$mif->dump_mif('newmif.mif');
DESCRIPTION
The Local::MifTree class is implemented as a Tree::DAG_Node
subclass, and thus inherits all the methods of that class.
Two methods are overridden. Please read Tree::DAG_Node to
see what other methods are available.
MIF (Maker Interchange Format) is an Adobe FrameMaker file
format in ASCII, consisting of statements that create an
easily parsed, readable text file of all the text, graphics,
formatting, and layout constructs that FrameMaker
understands. Because MIF is an alternative representation of
a FrameMaker document, it allows FrameMaker and other
applications to exchange information while preserving
graphics, document content, and format.
This document does not tell you what the syntax of a MIF
file is, nor does it document the meaning of the MIF
statements. For this, please read (and re-read) the
MIF_Reference.pdf, provided by Adobe.
MifTree not only knows the MIF syntax, but it also has some
understanding of the allowed structures (within their
contexts) and attribute types. The file
Local/MifTree/MifTreeTags holds all the valid MIF statements
and the attribute type for every statement. This file may
need some improvement, as it is created by analyzing a large
collection of MIF files written by FrameMaker (and an
automatic analysis of the *MIF Reference*, which showed
several typos and inconsistencies in that manual). The
current file is for MIF version 7.00.
Dependencies
This class implementation depends on the following modules,
all available from CPAN:
* Tree::DAG_Node
* IO::Tokenized and IO::Tokenized::File and the
custom-made IO::Tokenized::Scalar
* IO::Stringy (only IO::Scalar is needed)
Overridden Methods
add_daughters(LIST)
Adds a list of daughter object to a node. The difference
with the DAG_Node method is that it checks for a valid
MIF construct. Only the mother/daughter relationship is
checked.
attributes(VALUE)
The attributes method of the Local::MifTree class does
not require a reference as an attribute, as does the
DAG_Node equivalent. As an extra, the method checks if
the method is called on a leaf, since the MIF structure
does not allow attributes on non-ending nodes. The
method reads/sets the raw attribute, no string
conversion, path encoding/decoding or value extraction
is done. To obtain or set one of those values, use the
specific "Attribute Methods" mentioned below.
Quick Creators
The following methods can be used instead of the DAG_Node
standard methods to build your MIF structure. It's just a
lazy way of adding daughters, but it improves readability of
your code if you create something like:
my $mif = Local::MifTree->new->add_node(
AFrames => Local::MifTree->add_node(
Frame => Local::MifTree->add_node(
ImportObject => Local::MifTree->add_leaf(
ImportObFileDI => encode_path('c:\bar\foo.eps'))
),
Local::MifTree->add_node(
ImportObject => Local::MifTree->add_leaf(
ImportObFileDI => encode_path('../../foo/boo.eps'))
)
)
);
"add_leaf(MIFSTATEMENT, ATTRIBUTE or GRANDDAUGHTERLIST)"
Adds a new daughter to the object. The first argument
specifies the name, all the following arguments are
taken either as the attribute for the leaf, or as a list
of granddaughter objects to add to the newly created
daughter. (In MIFTree world, newly born daughters mature
in split seconds.)
"add_node(MIFSTATEMENT, ATTRIBUTE or GRANDDAUGHTERLIST)"
An exact synonym for the "add_leaf" method.
"add_facet()"
Adds a facet to the object. In DAG_Node tree terms, this
is implemented as a leaf with the name "_facet" and a
filehandle to a temp file as its attribute.
Search in Tree
"$OBJ->daughters_by_name(NAMESTRING, RECURSE)"
Find all daughters that listen to the name NAMESTRING,
either walking the tree (RECURSE is true), or only on
the mother's daughters (RECURSE false or omitted).
Returns the first object in scalar context, or a list of
all found objects in list context.
Maybe one day I'll add magic to this function so you get
the next item if you call the method on the same object
without arguments.
Note that "daughter_by_name" is an exact alias for this
method.
"$OBJ->daughters_by_name_and_attr(NAMESTRING, ATTRIBUTE,
RECURSE)"
Find all daughters that listen to the name NAMESTRING
and have the raw attribute ATTRIBUTE, either walking the
tree (RECURSE is true), or only on the mother's
daughters (RECURSE false or omitted). Returns the first
object in scalar context, or a list of all found objects
in list context. ATTRIBUTE must be raw data, so use
"quote", "unquote", "encode_path" and "decode_path" as
appropriate.
If you specify an empty string or undef as the
NAMESTRING, this method will just look for ATTRIBUTE.
Note that "daughters_by_name_and_attr" is an exact alias
for this method.
"$OBJ->find_string(QUOTED_REGEX)"
Returns a list of all strings that match QUOTED_REGEX
under $OBJ. When called in scalar context, only the
first match is returned.
Attribute Methods
"$OBJ->string(STRING)"
Reads or sets the object's attribute as a MIF string.
The method just calls "quote" and "unquote" as
appropriate.
"$OBJ->pathname(PATHSTRING)"
Returns the object's attribute as local pathname, or
sets it to the device independent pathname. The method
just calls "encode_path" and "decode_path" as
appropriate. PATHSTRING must also be a local pathname.
"$OBJ->abs_pathname(FROMROOT)"
Returns the object's attribute as a local pathname. The
method just calls "decode_path", passing on the FROMROOT
argument. Use this method if you want to make sure that
you always receive absolute pathnames, independently
from what is stored in the attribute.
"$OBJ->boolean(BOOLEAN)"
Returns or sets the object's TRUE or FALSE value.
"$OBJ->measurements(LIST)"
Returns or sets a list of measurements. When called in
scalar context, only the first measurement is returned.
Everything is in the default unit of measurement. (Can
be set using "Local::MifTree->default_unit". If this
variable is set to the empty string (which also happens
to be the default), points are output.) You always get
the values without the unit specifier, so calculations
can be made directly on this. To get a value from the
list, do something like:
my $q;
$q = Local::MifTree->new->add_leaf(
PgfCellMargins => "0.0 pt 1.0 pt 2.0 pt 3.0 pt"
);
my $k = ($q->measurements)[1];
print "k is now: $k\n" # prints "k is now: 1"
In MIF, a maximum of four values can be supplied, but
this is never checked by this method.
"$OBJ->percentage(FRACTION)"
Returns or sets the object's percentage value as a
fraction (1 = 100%).
"$OBJ->facet_data()"
Returns the object's facet data as a list of lines. (Use
a "syswrite" to "facet_handle" to set the objects data.
Not a very elegant implementation, but I consider a
facet to be rather esoteric, and we have to be efficient
on memory usage as well...)
"$OBJ->facet_handle()"
Returns the filehandle to the object's facet data. Since
the temporary file is sysopened, you should use
"syswrite" instead of "print" to respect the buffering
considerations.
"Local::MifTree->default_unit(UNIT)"
This class method returns or sets the global default
units of measurement. See "convert" for a list of valid
assignments.
Local::MifTree's default units of measurement can (and
probably will) differ from the default <Units> that are
specified in the MIF file.
The default for "default_unit" is an empty string, which
means that no unit specifier will be output, and all
values are in "points".
Tests on Tree Object
"$OBJ->is_node()"
Tests if the object is a valid MIF node statement. That
is, if its name occurs in the %mifnodes hash. Returns a
list of valid daughters when a match is found. (In my
terminology, nodes can have daughters, whereas leaves
don't.)
"$OBJ->is_leaf()"
Tests if the object is a valid MIF leaf statement and
thus can have an attribute value. The name is just
looked up in the %mifleaves hash.
"$OBJ->allows_daughter(DAUGHTEROBJECT)"
Checks if a mother object can have a specific daughter
object. I just thought this could come in handy when you
want to bind one object tree to another.
"$OBJ->check_attribute"
Checks if the attribute conforms to the type. Currently
the following types are defined:
0xnnn
ID
L_T_R_B
L_T_W_H
W_H
W_W
X_Y
X_Y_W_H
boolean
data
degrees
dimension
empty *)
integer
keyword
number
pathname
percentage
seconds_microseconds
string
tagstring
*) no attribute allowed; some leaves and all nodes have this
The function returns TRUE if the attribute seems valid,
and FALSE if there is an error. Use get_attribute_error
to see the error.
"$OBJ->get_attribute_error"
Returns a meaningful text string if the attribute
appears to be invalid.
"$OBJ->validate(FROMROOT)"
Not yet implemented.
Validates a MIF tree object. If you set FROMROOT to
true, the validation starts from $OBJ->root, and special
checking is done on the root object. This special
behaviour s needed because the method cannot know if a
Local::MifTree object is to represent a complete MIF
file, and not just a fragment. So please remember always
to set FROMROOT if you want to validate a complete MIF
tree, even if $OBJ already points to the root object.
From/to MIF Syntax
"LIST = $obj->dump_mif()"
Dumps out the current tree as a list of MIF statements
in valid MIF file syntax. You can write the resulting
list to a file. The method tries to mimic the Adobe MIF
parser behaviour as closely as possible. Please note
that this method can be memory intensive, since it
creates a whole new copy of your MIF tree in memory. If
you just want to write the MIF tree to a file, you may
want to use dump_miffile instead.
"LIST = $obj->dump_miffile(FILENAME)"
Dumps out the current tree of MIF statements into a
valid MIF file syntax. The method returns with a FALSE
result if the file cannot be written.
"$OBJ->parse_mif(STRING)"
Parses a string of MIF statements into the object. This
is also a very quick way to set up an object tree:
my $new_obj = Local::MifTree->new();
$new_obj->parse_mif(<<ENDMIF);
<MIFFile 7.00># The only required statement
<Para # Begin a paragraph
<ParaLine# Begin a line within the paragraph
<String `Hello World'># The actual text of this document
> # end of Paraline #End of ParaLine statement
> # end of Para #End of Para statement
ENDMIF
Implemented by tying the scalar to a filehandle and
calling IO::Tokenizer on the resulting handle.
The parser currently has the following limitations:
* All comments are lost.
* Macro statements are not (yet) implemented.
* Include statements are not (yet) implemented.
Maybe I'll do something about it. Someday.
"$OBJ->parse_miffile(FILENAME)"
Parses a file from disk into a DAG_Node tree structure.
See parse_mif for details.
Old-style Functions
All these functions are exported by default.
quote(STRING)
Quotes a string with MIF style quotes, and escapes
forbidden characters. Backslashes, backticks, single
quotes, greater-than and tabs are escaped, non-ASCII
values are written in their hexadecimal representation.
So:
Some `symbols': > \ؿ!>
is written as
`Some \Qsymbols\q: \> \\\xaf \xc0 !'
As a special case, escaped hexadecimals are preserved in
the input string. If you want a literal \x00 string,
precede it with an extra backslash.
print quote("\x09 "); # prints `\x09 ', a forced return
in FrameMaker
print quote("\\x09 "); # prints `\\x09 '; this will show
up literally
# as \x09 in FrameMaker
unquote(STRING)
The opposite action. Surrounding quotes are removed and
all escaped sequences are transliterated into their
original character.
encode_path(STRING)
Encodes path names to the MIF path syntax. Usage:
$mifPathString =
encode_path('D:\Dos\Path\With\Backslashe
s\Filename');
$mifPathString =
encode_path('..\.. \Also\Relative\Path\Is\Allowed\Filename'
);
The path name must not be in a MIF quoted style. It
returns the device independent path name *with* the
quotes.
"decode_path(STRING, ROOTPATH)"
Usage:
print decode_path
('<v\>C:<c\>Mydir<c\>Subdir<c\>Filename');
# prints C:/Mydir/Subdir/Filename
print decode_path ('<u\><u\><c\>Subdir<c\>Filename');
# prints ../../Subdir/Filename
Currently only Windows path names are supported (meaning
that Unix and MacOS style path remain untested). MIF
string quotes are removed. ROOTPATH, if specified, is
the path that is prepended if STRING happens to be a
relative path.
"convert(VALUE_AND_OLDUNIT, NEWUNIT, SUPPRESSUNIT)"
Converts a value in one unit of measurement into
another. If you leave out the unit of measurement it
defaults to Local::MifTree->default_unit (not to the MIF
document's default unit of measurement!). Other
measurements are:
{
pt => 1 / 72,
point => 1 / 72,
" => 1,
in => 1,
mm => 1 / 25.4,
millimeter => 1 / 25.4,
cm => 1 / 2.54,
centimeter => 1 / 2.54,
pc => 1 / 6,
pica => 1 / 6,
dd => 0.01483,
didot => 0.01483,
cc => 12 * 0.01483,
cicero => 12 * 0.01483
}
The optional argument SUPPRESSUNIT determines if the
unit of measurement needs to be written in the result.
Note that you won't get a unit of measurement included
in your result when you leave out NEWUNIT and specify
"Local::MifTree->default_unit" to be the empty string,
even if you set SUPPRESSUNIT to be false. In that case
the returned value is in points. So
Local::MifTree->default_unit('');
print convert("12.0 didot"); # prints the value
in points: 12.8131
Local::MifTree->default_unit('mm');
print convert("12.0 didot", "pt", 1); # also prints
12.8131
Local::MifTree->default_unit('pt');
print convert("12.0 didot", '', 1); # also prints
12.8131
All values are rounded to 4 decimals.
SEE ALSO
* Adobe's *MIF_Reference.pdf*, included in FrameMaker's
online documentation.
* http://www.miffy.com, as this module was formerly called
Miffy.pm
AUTHOR
Roel van der Steen, roel-perl@st2x.net
COPYRIGHT AND LICENSE
Copyright 2004 by ITP
This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.
| |
| Roel van der Steen 2004-03-19, 12:55 pm |
| On Thu, 04 Mar 2004 at 22:28 GMT, Roel van der Steen wrote:
> I've written a new module FrameMaker::MifTree that I'm planning to put
> on CPAN. Please take a look at the documentation and tell me what you
> think.
>
> Also, I'm not sure if FrameMaker::MifTree is the right module name.
I left y'all speechless... so I'll proceed with the name
FrameMaker::MifTree
|
|
|
|
|