Re: initial release of DITA-plugin-utilities


Chris Papademetrious
 

I thought of another example, from our own books. Originally I had all of our domains, allowances, and disallowances defined in the document-type shell I used for my topics:


<topicshell filename="snpsTopicShell.rng">
<root_element>topic</root_element>
<include_domains>topic hi-d snps-d snpsm-t indexing-d sw-d pr-d ui-d mathml-d deliveryTarget style</include_domains>
<allow domain="hi-d" elements="sup sub"/>
<allow domain="sw-d" elements="filepath cmdname"/>
<allow domain="pr-d" elements="codeph"/>
<allow domain="ui-d" elements="menucascade uicontrol"/>
<disallow elements="alt audience author bodydiv boolean brand category cmdname component copyrholder copyright copyryear created critdates data data-about desc div draft-comment example featnum figgroup filepath gui-section index-base index-see index-see-also index-sort-as indextermref itemgroup keyword lines linkinfo linklist linkpool longdescref longquoteref lq mathmlref navtitle object othermeta param permissions platform prodinfo prodname prognum publisher q resourceid revised searchtitle sectiondiv series shortdesc simpletable sl sli source state stentry sthead strow titlealts tm vrm vrmlist"/>
</topicshell>


But eventually I realized that I needed to replicate all this in a glossary document-type shell too. I didn't like the idea of replicating and maintaining this stuff in two places, so I moved it to a constraint module, then included that constraint in both my topic and glossary docshells:


<constraint domain="snps-c">
<include_domains>topic hi-d snps-d snpsm-t indexing-d sw-d pr-d ui-d mathml-d deliveryTarget style</include_domains>
<allow domain="hi-d" elements="sup sub"/>
<allow domain="sw-d" elements="filepath cmdname"/>
<allow domain="pr-d" elements="codeph"/>
<allow domain="ui-d" elements="menucascade uicontrol"/>
<disallow elements="alt audience author bodydiv boolean brand category cmdname component copyrholder copyright copyryear created critdates data data-about desc div draft-comment example featnum figgroup filepath gui-section index-base index-see index-see-also index-sort-as indextermref itemgroup keyword lines linkinfo linklist linkpool longdescref longquoteref lq mathmlref navtitle object othermeta param permissions platform prodinfo prodname prognum publisher q resourceid revised searchtitle sectiondiv series shortdesc simpletable sl sli source state stentry sthead strow titlealts tm vrm vrmlist"/>
<constrain elements="topic"><nesting model="(topic.element|module.element)*"/></constrain>
</constraint>

<topicshell filename="snpsGlossaryShell.rng">
<title>Synopsys Glossary</title>
<header>some header</header>
<root_element>glossgroup</root_element>
<include_domains>snps-c glossgroup glossentry</include_domains>
</topicshell>

<topicshell filename="snpsTopicShell.rng">
<title>Synopsys Glossary</title>
<header>some header</header>
<root_element>topic</root_element>
<include_domains>snps-c</include_domains>
</topicshell>


It literally took less than a minute to do this, including creating the new plugin directory. It becomes very easy to play around with different plugin structures when describing everything at a high level.


- Chris


---In dita-users@yahoogroups.com, <chrispitude@...> wrote :

Hi Mark,


Yes, that's right. You give it a high-level description as input, and it makes a DITA grammar plugin directory as output - complete with plugin.xml and catalog.xml files.


I can share two simple examples to give you an idea.


Let's say you want to disallow <table> and <simpletable> in a <note> element:


<constraint domain="myconst-c">
<constrain elements="note">
<disallow elements="table simpletable"/>
</constrain>
</constraint>




This results in the following module:


<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="urn:oasis:names:tc:dita:rng:vocabularyModuleDesc.rng"
schematypens="http://relaxng.org/ns/structure/1.0"?>


<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
xmlns:dita="http://dita.oasis-open.org/architecture/2005/" xmlns:sch="http://purl.oclc.org/dsdl/schematron">
<moduleDesc xmlns="http://dita.oasis-open.org/architecture/2005/">
<moduleTitle>constraint Module for myconst-c Domain</moduleTitle>
<headerComment>Header Comment for constraint Module for myconst-c Domain</headerComment>
<moduleMetadata>
<moduleType>constraint</moduleType>
<moduleShortName>myconst-c</moduleShortName>
<modulePublicIds>
<rngMod>com:test:ex1:myconstConstraintMod.rng<var name="ditaver" presep=":"/></rngMod>
</modulePublicIds>
<domainsContribution>(topic myconst-c)</domainsContribution>
</moduleMetadata>
</moduleDesc>
<div>
<a:documentation>CONTENT MODEL OVERRIDES</a:documentation>
<include href="urn:oasis:names:tc:dita:rng:topicMod.rng">
<!--provided domains: topic-->
<!--provided elements from 'topic': abstract alt audience author body bodydiv boolean brand category cite colspec component copyrholder copyright copyryear created critdates data data-about dd ddhd desc div dl dlentry dlhead draft-comment dt dthd entry example featnum fig figgroup fn foreign image index-base indexterm indextermref itemgroup keyword keywords li lines link linkinfo linklist linkpool linktext longdescref longquoteref lq metadata navtitle no-topic-nesting
note object ol othermeta p param permissions ph platform pre prodinfo prodname prognum prolog publisher q related-links required-cleanup resourceid revised row searchtitle section sectiondiv series shortdesc simpletable sl sli source state stentry sthead strow table tbody term text tgroup thead title titlealts tm topic ul unknown vrm vrmlist xref-->
<define name="note.content">
<ref name="note.content__myconst-c"/>
</define>
</include>
</div>
<div>
<a:documentation>EXTRA CONTENT MODELS</a:documentation>
<define name="note.content__myconst-c">
<zeroOrMore>
<choice>
<text/>
<ref name="dl"/>
<ref dita:since="1.3" name="div"/>
<ref name="fig"/>
<ref name="image"/>
<ref name="lines"/>
<ref name="lq"/>
<ref name="object"/>
<ref name="ol"/>
<ref name="p"/>
<ref name="pre"/>
<!--<ref name="simpletable.element"/>-->
<ref name="sl"/>
<!--<ref name="table.element"/>-->
<ref name="ul"/>
<ref name="basic.ph"/>
<ref name="data.elements.incl"/>
<ref name="foreign.unknown.incl"/>
<ref name="txt.incl"/>
</choice>
</zeroOrMore>
</define>
</div>
</grammar>



The utility finds where <note> is defined in the OASIS modules and includes that module by URN, then overrides its content model in the recommended fashion - recursing into the content model, modifying only what's necessary, and preserving as many references back up through the reference hierarchy as possible.


A second example is that you want to selectively use a few elements from various domains:


<topicshell filename="myTopicShell.rng">
<root_element>topic</root_element>
<include_domains>hi-d pr-d ui-d</include_domains>
<allow domain="hi-d" elements="sup sub"/>
<allow domain="pr-d" elements="codeph"/>
<allow domain="ui-d" elements="menucascade uicontrol"/>
</topicshell>


This results in the following file:


<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="urn:oasis:names:tc:dita:rng:vocabularyModuleDesc.rng"
schematypens="http://relaxng.org/ns/structure/1.0"?>


<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns:dita="http://dita.oasis-open.org/architecture/2005/" xmlns:sch="
http://purl.oclc.org/dsdl/schematron">
<moduleDesc xmlns="http://dita.oasis-open.org/architecture/2005/">
<moduleTitle>topicshell Module for topic</moduleTitle>
<headerComment>Header Comment for topicshell Module for topic</headerComment>
<moduleMetadata>
<moduleType>topicshell</moduleType>
<moduleShortName>topicshell Module for topic</moduleShortName>
<modulePublicIds>
<rngShell>:myTopicShell.rng<var name="ditaver" presep=":"/></rngShell>
</modulePublicIds>
</moduleMetadata>
</moduleDesc>
<div>
<a:documentation>ROOT ELEMENT DECLARATION</a:documentation>
<start>
<ref name="topic.element"/>
</start>
</div>
<div>
<a:documentation>DOMAINS ATTRIBUTE</a:documentation>
<define combine="interleave" name="domains-att">
<optional>
<attribute a:defaultValue="(topic hi-d) (topic pr-d) (topic ui-d)" name="domains"/>
</optional>
</define>
</div>
<div>
<a:documentation>CONTENT CONSTRAINT INTEGRATION</a:documentation>
</div>
<div>
<a:documentation>MODULE INCLUSIONS</a:documentation>
<include href="urn:oasis:names:tc:dita:rng:topicMod.rng">
<!--provided domains: topic-->
<!--provided elements from 'topic': abstract alt audience author body bodydiv boolean brand category cite colspec component copyrholder copyright copyryear created critdates data data-about dd ddhd desc div dl dlentry dlhead draft-comment dt dthd entry example featnum fig figgroup fn foreign image index-base indexterm indextermref itemgroup keyword keywords li lines link linkinfo linklist linkpool linktext longdescref longquoteref lq metadata navtitle no-topic-nesting
note object ol othermeta p param permissions ph platform pre prodinfo prodname prognum prolog publisher q related-links required-cleanup resourceid revised row searchtitle section sectiondiv series shortdesc simpletable sl sli source state stentry sthead strow table tbody term text tgroup thead title titlealts tm topic ul unknown vrm vrmlist xref-->
<define name="topic-info-types">
<ref name="info-types"/>
</define>
</include>
<include href="urn:oasis:names:tc:dita:rng:highlightDomain.rng">
<!--provided domains: hi-d-->
<define name="b.element">
<notAllowed/>
</define>
<define name="i.element">
<notAllowed/>
</define>
<define name="line-through.element">
<notAllowed/>
</define>
<define name="overline.element">
<notAllowed/>
</define>
<define name="tt.element">
<notAllowed/>
</define>
<define name="u.element">
<notAllowed/>
</define>
<!--provided elements from 'hi-d': sub sup-->
</include>
<include href="urn:oasis:names:tc:dita:rng:programmingDomain.rng">
<!--provided domains: pr-d-->
<define name="apiname.element">
<notAllowed/>
</define>
<define name="codeblock.element">
<notAllowed/>
</define>
<define name="coderef.element">
<notAllowed/>
</define>
<define name="delim.element">
<notAllowed/>
</define>
<define name="fragment.element">
<notAllowed/>
</define>
<define name="fragref.element">
<notAllowed/>
</define>
<define name="groupchoice.element">
<notAllowed/>
</define>
<define name="groupcomp.element">
<notAllowed/>
</define>
<define name="groupseq.element">
<notAllowed/>
</define>
<define name="kwd.element">
<notAllowed/>
</define>
<define name="oper.element">
<notAllowed/>
</define>
<define name="option.element">
<notAllowed/>
</define>
<define name="parml.element">
<notAllowed/>
</define>
<define name="parmname.element">
<notAllowed/>
</define>
<define name="pd.element">
<notAllowed/>
</define>
<define name="plentry.element">
<notAllowed/>
</define>
<define name="pt.element">
<notAllowed/>
</define>
<define name="repsep.element">
<notAllowed/>
</define>
<define name="sep.element">
<notAllowed/>
</define>
<define name="synblk.element">
<notAllowed/>
</define>
<define name="synnote.element">
<notAllowed/>
</define>
<define name="synnoteref.element">
<notAllowed/>
</define>
<define name="synph.element">
<notAllowed/>
</define>
<define name="syntaxdiagram.element">
<notAllowed/>
</define>
<define name="var.element">
<notAllowed/>
</define>
<!--provided elements from 'pr-d': codeph-->
</include>
<include href="urn:oasis:names:tc:dita:rng:uiDomain.rng">
<!--provided domains: ui-d-->
<define name="screen.element">
<notAllowed/>
</define>
<define name="shortcut.element">
<notAllowed/>
</define>
<define name="wintitle.element">
<notAllowed/>
</define>
<!--provided elements from 'ui-d': menucascade uicontrol-->
</include>
</div>
<div>
<a:documentation>ID-DEFINING-ELEMENT OVERRIDES</a:documentation>
<define name="any">
<zeroOrMore>
<choice>
<ref name="idElements"/>
<element>
<anyName>
<except>
<name>topic</name>
</except>
</anyName>
<zeroOrMore>
<attribute>
<anyName/>
</attribute>
</zeroOrMore>
<ref name="any"/>
</element>
<text/>
</choice>
</zeroOrMore>
</define>
</div>
</grammar>



The utility identifies any elements that require idElement or namespace handling. It understands domains that implicitly provide other domains upon inclusion, even when overriding content models that a couple of includes deep. It takes care of all the domain contribution stuff for you.


The utility runs in a few seconds, so basically you can interactively craft grammars in one window and try them out in another window (e.g. Oxygen XML).



- Chris



---In dita-users@yahoogroups.com, <mark@...> wrote :

Thanks for this Chris. Just so I understand, is this a simplified method for making DITA specializations using RelaxNG schemas?

Regards,
Mark Giffin
Mark Giffin Consulting, Inc.
http://www.markgiffin.com/ http://www.markgiffin.com/

On 23-May-19 9:28 AM, chrispitude@... mailto:chrispitude@... [dita-users] wrote:

Hi everyone,


I'm happy to announce the initial release of my DITA-plugin-utilities github repo:


https://github.com/chrispy-snps/DITA-plugin-utilities https://github.com/chrispy-snps/DITA-plugin-utilities



There are two linux-based utilities provided:
make_dita_grammar.pl - make DITA RelaxNG grammar plugin modules from high-level descriptions content_model.pl - show the content model of a DITA RelaxNG topicshell or mapshell module
make_dita_grammar.pl lets you create DITA grammars from high-level XML descriptions. For example,


<specialize elements="fig1" from="fig"/>


The output is a plugin directory that is ready to be placed in your DITA-OT plugins/ directory and installed/integrated.



content_model.pl lets you report the content model of DITA topicshell and mapshell modules:


$ content_model.pl ex1/rng/myTopicShell.rng -attributes none

abstract = element abstract { (text | dl | \div | fig | fig1 | image | lines | lq | note | object | ol | p | pre | simpletable | sl | table | ul | boolean | cite | keyword | ph | q | term | \text | tm | xref | state | data | data-about | foreign | unknown | shortdesc | draft-comment | fn | indextermref | indexterm | r
equired-cleanup)+ }
alt = element alt { (text | data | data-about | foreign | unknown | keyword | term | \text | draft-comment | required-cleanup | ph)+ }
audience = element audience { empty }
author = element author { (text | data | data-about | foreign | unknown | keyword | term | \text)+ }
body = element body { (dl | \div | fig | fig1 | image | lines | lq | note | object | ol | p | pre | simpletable | sl | table | ul | data | data-about | draft-comment | foreign | unknown | required-cleanup | bodydiv | example | section)* }
...omitted...
topic = element topic { title, titlealts?, (shortdesc | abstract)?, prolog?, body?, related-links?, topic* }
ul = element ul { (data | data-about)*, li+ }
unknown = element unknown { (topic? | _1 | text)+ }
vrm = element vrm { empty }
vrmlist = element vrmlist { vrm+ }
xref = element xref { (text | boolean | keyword | ph | q | term | \text | tm | state | cite | data | data-about | draft-comment | foreign | unknown | required-cleanup | image | desc)+ }



To better understand how grammar creation works, have a look at the input XML files and resulting output DITA plugin directories at


https://github.com/chrispy-snps/DITA-plugin-utilities/tree/master/examples https://github.com/chrispy-snps/DITA-plugin-utilities/tree/master/examples



This is an initial release, so expect bugs and rough edges. But, it's working enough that we're using it in-house for grammar creation.


Feel free to reply with questions!



- Chris

Join main@dita-users.groups.io to automatically receive all group messages.