Name

Dita::Project - Xml to Dita conversion utilities

Synopsis

A collection of methods useful for converting Xml representing documentation to the Dita standard.

use Dita::Project;
use Data::Table::Text qw(nws writeFile);
use Test::More qw(no_plan);

my $source = writeFile(q(a.xml), <<END);                                      # Create a source file containing xml
<section>
  <title>How to do something</title>
  <para>Do the following:</para>
  <ol>
    <li>Read the book</li>
    <li>Apply the ideas</li>
    <li>consider the results</li>
  </ol>
</section>
END

my $project = Dita::Project::new(name=>q(docbook), source=>$source);          # Create a project from the source file

$project->parseSource;                                                        # Create an xml parse tree for the project

$project->contextFreeConversionsFromDocBookToDita;                            # Do the obvious conversions to Dita

$project->parse x= sub                                                        # Task specific edits
 {$project->listToSteps($_)                      if $_->at(qw(ol));           # Change list to steps
  $_->change(q(context))                         if $_->at(qw(p));            # Paragraph to context
  $_->next->wrapTo($_->lastSibling, q(taskbody)) if $_->at(qw(title));        # Wrap content in task body
  $_->change(q(task))->id = "t1"                 if $_->at(qw(section));      # Make the section a task
 };

 ok -p $project->parse eq <<END;                                              # Print the resulting parse tree
<task id="t1">
  <title>How to do something</title>
  <taskbody>
    <context>Do the following:</context>
    <steps>
      <step>
        <cmd>Read the book</cmd>
      </step>
      <step>
        <cmd>Apply the ideas</cmd>
      </step>
      <step>
        <cmd>consider the results</cmd>
      </step>
    </steps>
  </taskbody>
</task>
END

if (qx(xmllint -version) =~ m(\Axmllint: using libxml version)s)              # Lint if xmllint is available
 {$project->lintTopic(q(task.dita));                                          # Save and lint the topic to a file
  Dita::Project::waitLints;                                                   # Wait for lint to finish

  my $report = Dita::Project::reportLints(q(summary.txt), qw(. dita));        # Create lint report by examining all completed lints

  ok nws($report->print =~ s(on ....-..-.. at ..:..:..) ()gsr) eq nws(<<END); # Check lint report after normalizing whitespace and date

   100 % success converting 1 projects containing 1 xml files

   Passes: 1   Fails: 0    Errors: 0

   ProjectStatistics
     #  Percent   Pass  Fail  Total  Project
     1 100.0000      1     0      1  docbook

  END
 }

Description

Xml to Dita conversion utilities

The following sections describe the methods in each functional area of this module. For an alphabetic listing of all methods by name see Index.

Methods

Xml to Dita conversion utilities.

new()

Create a project to describe the conversion of one source file containing xml representing documentation into one or more Dita topics.

Example:

my $p = new(name=>q(a), source=>fpe($dir, 1, q(xml)));

ok $p->source eq qq($dir/1.xml);

This is a static method and so should be invoked as:

Dita::Project::new

name :lvalue

Name of project.

number :lvalue

Number of the project.

parse :lvalue

Parse of the project.

source :lvalue

Input file containing the source xml.

title :lvalue

Title of the project.

loadFolder($)

Create a project for each dita/ditamap/doc/xml file in and below the specified folder.

   Parameter  Description
1  $dir       Folder

Example:

map {writeFile(fpe($dir, $_, q(xml)), <<END)} 1..9;
<concept id="c$_">
  <title>Title</title>
  <conbody>
    <para>pppp</para>
  </conbody>
</concept>
END

loadFolder($dir);

ok projects         == 9;

ok project(1)->name == 1;

is_deeply [matching(qr(1|2))],

[bless({ name => 1, number => 0, source =>qq($dir/1.xml)}, "Dita::Project"),

bless({ name => 2, number => 1, source =>qq($dir/2.xml)}, "Dita::Project"),

This is a static method and so should be invoked as:

Dita::Project::loadFolder

projects()

List all the projects defined.

Example:

map {writeFile(fpe($dir, $_, q(xml)), <<END)} 1..9;
<concept id="c$_">
  <title>Title</title>
  <conbody>
    <para>pppp</para>
  </conbody>
</concept>
END

loadFolder($dir);

ok projects         == 9;

project($)

Details of a specific project.

   Parameter  Description
1  $name      Name of the project

Example:

map {writeFile(fpe($dir, $_, q(xml)), <<END)} 1..9;
<concept id="c$_">
  <title>Title</title>
  <conbody>
    <para>pppp</para>
  </conbody>
</concept>
END

loadFolder($dir);

ok projects         == 9;

ok project(1)->name == 1;

matching($)

List of projects whose names match the specified regular expression.

   Parameter  Description
1  $re        Regular expression to select projects by name

Example:

map {writeFile(fpe($dir, $_, q(xml)), <<END)} 1..9;
<concept id="c$_">
  <title>Title</title>
  <conbody>
    <para>pppp</para>
  </conbody>
</concept>
END

loadFolder($dir);

ok projects         == 9;

is_deeply [matching(qr(1|2))],

[bless({ name => 1, number => 0, source =>qq($dir/1.xml)}, "Dita::Project"),

bless({ name => 2, number => 1, source =>qq($dir/2.xml)}, "Dita::Project"),

parseSource($)

Parse a project from its source file and the resulting parse tree.

   Parameter  Description
1  $project   Project

Example:

ok -p $p->parseSource eq <<END;
<concept id="c1">
  <title>Title</title>
  <conbody>
    <para>pppp</para>
  </conbody>
</concept>
END

topicTypeAndBody($$)

Topic type and corresponding body.

   Parameter  Description
1  $project   Project
2  $type      Type - concept; bookmap etc

Example:

is_deeply [project(2)->topicTypeAndBody(q(concept))],

["concept", "Concept", "conbody"];

This is a static method and so should be invoked as:

Dita::Project::topicTypeAndBody

xmlHeaders($$$)

Add xml headers for each document type to a string of xml.

   Parameter  Description
1  $project   Project
2  $type      Type - concept; bookmap etc
3  $string    String of xml

Example:

ok project(1)->xmlHeaders(qw(concept <a/>)) eq <<END;
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd" []>
<a/>
END

catalogName()

The Dita Xml catalog to use to validate topics. Assign the file name of the catalog on your computer to this lvalue method.

catalogNameBM()

The Dita Xml catalog to use to validate bookmaps. Assign the file name of the catalog on your computer to this lvalue method.

lintTopic($$$)

Lint a topic by writing the optional xml to a file and invoking xmllint on the file. If the xml is not specified the current parse tree is printed and so used as the source of the xml.

   Parameter  Description
1  $project   Project
2  $file      File
3  $string    Optional string of xml else the current parse tree will be printed

Example:

project(1)->lintTopic(fpe($dir, qw(out dita)),

project(1)->xmlHeaders(qw(concept), <<END));
<concept id="c1">
  <title>Title</title>
  <conbody>
    <p>ppp</p>
  </conbody>
</concept>
END

waitLints;

lintBookMap($$$)

Lint a bookmap by writing the optional xml to a file and invoking xmllint on the file. If the xml is not specified the current parse tree is printed and so used as the source of the xml.

   Parameter  Description
1  $project   Project
2  $file      File
3  $string    Optional string of xml else the current parse tree will be printed

Example:

project(1)->lintBookMap(fpe($dir, qw(bookmap dita)),

project(1)->xmlHeaders(qw(bookmap), <<END));
<bookmap>
  <booktitle>
    <mainbooktitle>Title</mainbooktitle>
  </booktitle>
  <chapter href="1.dita" navtitle="Project 1"/>
</bookmap>
END

waitLints()

Wait for all lints to finish.

Example:

project(1)->lintTopic(fpe($dir, qw(out dita)),

project(1)->xmlHeaders(qw(concept), <<END));
<concept id="c1">
  <title>Title</title>
  <conbody>
    <p>ppp</p>
  </conbody>
</concept>
END

project(1)->lintBookMap(fpe($dir, qw(bookmap dita)),

project(1)->xmlHeaders(qw(bookmap), <<END));
<bookmap>
  <booktitle>
    <mainbooktitle>Title</mainbooktitle>
  </booktitle>
  <chapter href="1.dita" navtitle="Project 1"/>
</bookmap>
END

waitLints;

This is a static method and so should be invoked as:

Dita::Project::waitLints

reportLints($@)

Report results of lints over selected folders and file extensions.

   Parameter                      Description
1  $reportFile                    File to write report to
2  @folderNamesAndFileExtensions  Folder names and file extensions to report over

Example:

project(1)->lintTopic(fpe($dir, qw(out dita)),

project(1)->xmlHeaders(qw(concept), <<END));
<concept id="c1">
  <title>Title</title>
  <conbody>
    <p>ppp</p>
  </conbody>
</concept>
END

project(1)->lintBookMap(fpe($dir, qw(bookmap dita)),

project(1)->xmlHeaders(qw(bookmap), <<END));
<bookmap>
  <booktitle>
    <mainbooktitle>Title</mainbooktitle>
  </booktitle>
  <chapter href="1.dita" navtitle="Project 1"/>
</bookmap>
END

waitLints;

This is a static method and so should be invoked as:

Dita::Project::reportLints

requiredCleanUpComment($$)

Required cleanup comment.

   Parameter  Description
1  $id        Clean up id
2  $string    Comment as a string

Example:

ok requiredCleanUpComment(1, q(aaa)) eq  nws(<<END);
<required-cleanup id="1">aaa</required-cleanup>
END

This is a static method and so should be invoked as:

Dita::Project::requiredCleanUpComment

requiredCleanUp($$)

Replace a node with a required cleanup node around the text of the replaced node.

   Parameter  Description
1  $project   Project
2  $node      Parse tree node

Example:

ok nws(<<END) eq nws(-p $p->requiredCleanUp(Data::Edit::Xml::new(<<END2)));
<required-cleanup id="a">&lt;a&gt;
  &lt;b&gt;bbb
  &lt;/b&gt;
&lt;/a&gt;
</required-cleanup>
END

uniqueCounter($)

The next unique number in a set of counters.

   Parameter  Description
1  $set       Counter set name

Example:

ok uniqueCounter(q(a)) eq q(a1);

ok uniqueCounter(q(a)) eq q(a2);

ok uniqueCounter(q(b)) eq q(b1);

This is a static method and so should be invoked as:

Dita::Project::uniqueCounter

titleToFileName($$$)

Create a unique file name from a title.

   Parameter  Description
1  $project   Project
2  $title     Title
3  $ext       Desired extension - defaults to .dita

Example:

ok project(1)->titleToFileName("title") eq q(title.dita);

convertListToSteps($$$)

Change ol/ul to steps.

   Parameter  Description
1  $project   Project
2  $o         List node in parse tree
3  $s         "step" or "substep"

listToSteps($$$)

Change ol/ul to steps.

   Parameter  Description
1  $project   Project
2  $o         List node in parse tree
3  $s         "step" or "substep"

Example:

ok -p project(1)->listToSteps(Data::Edit::Xml::new(<<FIN)) eq <<END;
<ol>
  <li>command 1</li>
  <li>command 2</li>
</ol>
FIN
<steps>
  <step>
    <cmd>command 1</cmd>
  </step>
  <step>
    <cmd>command 2</cmd>
  </step>
</steps>
END

stepsToList($$)

Change steps to ol.

   Parameter  Description
1  $project   Project
2  $o         Steps node in parse tree

Example:

ok -p project(1)->stepsToList(Data::Edit::Xml::new(<<FIN)) eq <<END;
<steps>
  <step><cmd>command 1</cmd></step>
  <step><cmd>command 2</cmd></step>
</steps>
FIN
<ol>
  <li>command 1</li>
  <li>command 2</li>
</ol>
END

contextFreeConversionsFromDocBookToDita($)

Make obvious changes to the parse tree of a DocBook file to make it look more like Dita.

   Parameter  Description
1  $project   Project

Example:

ok -p $p->parseSource eq <<END;
<concept id="c1">
  <title>Title</title>
  <conbody>
    <para>pppp</para>
  </conbody>
</concept>
END

$p->parseSource;

ok -p $p->contextFreeConversionsFromDocBookToDita eq <<END;
<concept id="c1">
  <title>Title</title>
  <conbody>
    <p>pppp</p>
  </conbody>
</concept>
END

Index

1 catalogName

2 catalogNameBM

3 contextFreeConversionsFromDocBookToDita

4 convertListToSteps

5 lintBookMap

6 lintTopic

7 listToSteps

8 loadFolder

9 matching

10 name

11 new

12 number

13 parse

14 parseSource

15 project

16 projects

17 reportLints

18 requiredCleanUp

19 requiredCleanUpComment

20 source

21 stepsToList

22 title

23 titleToFileName

24 topicTypeAndBody

25 uniqueCounter

26 waitLints

27 xmlHeaders

Installation

This module is written in 100% Pure Perl and, thus, it is easy to read, use, modify and install.

Standard Module::Build process for building and installing modules:

perl Build.PL
./Build
./Build test
./Build install

Author

philiprbrenan@gmail.com

http://www.appaapps.com

Copyright

Copyright (c) 2016-2018 Philip R Brenan.

This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.