Create different documents from the same sources via Jinja (object method)
With Jinja, you can define objects (audience, platform, version, etc.) and include or exclude text blocks according to their attributes. For a simpler introductory approach, see creating different documents from the same sources using Jinja. The same conditional-text concept also applies to DITA XML’s ditaval mechanism.
-
Create the following
conditional-text.rstfile:Using conditional text================================={% if public.elec %}.. admonition:: Danger for electriciansRisk of electrocutionDo not touch electrical wires.{% else %}.. admonition:: Danger for plumbersRisk of drowningDo not dive into the pool.{% endif %} -
Define an Audience class with two attributes for plumbers and electricians:
class Audience:def __init__(self,electrician,plumber):self.elec=electricianself.plum=plumber -
Create an instance of the Audience class whose value is true for electricians and false for plumbers:
user=Audience(True,False) -
Create and run the following script:
#!/usr/bin/env python3class Audience:def __init__(self,electrician,plumber):self.elec=electricianself.plum=plumberimport jinja2import sysuser=Audience(True,False)env = jinja2.Environment(loader=jinja2.FileSystemLoader('./'))template = env.get_template('conditional-text.rst')string=template.render(public=user)print(string) -
The contents of the
conditional-text.rstfile are overwritten and contain only the information intended for electricians. -
Create a condition for audiences other than electricians or plumbers:
Using conditional text================================={% if public.elec %}.. admonition:: Danger for electriciansRisk of electrocutionDo not touch electrical wires.{% elif public.plum %}.. admonition:: Danger for plumbersRisk of drowningDo not dive into the pool.{% else %}.. admonition:: No dangerIf you're not a plumber or an electrician, you're not in any danger.{% endif %} -
Create a new class for seasons:
class Season:def __init__(self,winter,spring,summer,autumn):self.wint=winterself.spri=springself.summ=summerself.autu=autumn -
Create more complex conditions:
Using conditional text================================={% if public.elec %}.. admonition:: Danger for electriciansRisk of electrocutionDo not touch electrical wires.{% elif public.plum and seas.wint %}.. admonition:: Danger for plumbersRisk of fractureDo not dive into the frozen pool.{% elif public.plum and seas.summ %}.. admonition:: Danger for plumbersRisk of hydrocutionDo not dive into cold water when it is hot.{% elif public.plum and seas.spri or seas.autu %}.. admonition:: Danger for plumbersRisk of somethingDon't dive into the pool, you never know.{% else %}.. admonition:: No dangerIf you're not a plumber or an electrician, you're not in any danger.{% endif %} -
Vary the values of the Audience and Season class instances to filter the content of the
conditional-text.rstfile.#!/usr/bin/env python3class Audience:def __init__(self,electrician,plumber):self.elec=electricianself.plum=plumberclass Season:def __init__(self,winter,spring,summer,autumn):self.wint=winterself.spri=springself.summ=summerself.autu=autumnimport jinja2import sysuser=Audience(False,True)when=Season(False,False,False,True)env = jinja2.Environment(loader=jinja2.FileSystemLoader('./'))template = env.get_template('conditional-text.rst')string=template.render(public=user,seas=when)print(string) -
Use a more readable variant in the content file:
It may be more intuitive to specify a user-friendly string value in the content file, especially if editors are unfamiliar with object-oriented programming, as the
==equality test is more meaningful to most people.Using conditional text================================={% if public.personae == "electrician" %}.. admonition:: Danger for electriciansRisk of electrocutionDo not touch electrical wires.{% elif public.personae == "plumber" and public.season == "winter" %}.. admonition:: Danger for plumbersRisk of fractureDo not dive into the frozen pool.{% elif public.personae == "plumber" and public.season == "summer" %}.. admonition:: Danger for plumbersRisk of hydrocutionDo not dive into cold water when it is hot.{% elif public.personae == "plumber" and public.season == "spring" or public.season == "autumn" %}.. admonition:: Danger for plumbersRisk of somethingDon't dive into the pool, you never know.{% else %}.. admonition:: No dangerIf you're not a plumber or an electrician, you're not in any danger.{% endif %}It’s more economical to use a single object class, even if it does mix apples and oranges (as much in this far-fetched example as in real life, where you’d mix audiences, versions, platforms, etc.).
#!/usr/bin/env python3class Audience:def __init__(self,pers,seas):self.personae=persself.season=seasimport jinja2import sysuser=Audience("plumber", "winter")env = jinja2.Environment(loader=jinja2.FileSystemLoader('./'))template = env.get_template('conditional-text.rst')string=template.render(public=user)print(string) -
Modify your script to indicate the public and the season as parameters:
#!/usr/bin/env python3# coding: utf8import jinja2import sysclass Audience:def __init__(self, pers, seas):self.personae = persself.season = seaspublic = ('electrician', 'plumber')four_seasons = ('winter', 'spring', 'summer', 'autumn')if len(sys.argv) == 3:pubparam = str(sys.argv[1])seasparam = str(sys.argv[2])if pubparam in public and seasparam in four_seasons:user = Audience(pubparam, seasparam)env = jinja2.Environment(loader=jinja2.FileSystemLoader('./'))template = env.get_template('conditional-text.rst')string = template.render(public=user)print(string)else:print('''Accepted values:\nelectrician or plumber as the 1st parameter\nwinter,spring, summer, autumn as the 2nd parameter''')else:print('Please indicate the audience and the season')Usage:
Terminal window ./profiling.py plumber autumnIf you’ve been paying close attention, you’ll have noticed that this script renders the else condition in the content file useless, since the parameter values are tested before execution.
To allow the passage of unexpected values and display the contents of the else block, the code must be modified as follows:
#!/usr/bin/env python3# coding: utf8class Audience:def __init__(self,pers,seas):self.personae=persself.season=seasimport jinja2import sysif len(sys.argv) == 3:pubparam=str(sys.argv[1])seasparam=str(sys.argv[2])user=Audience(pubparam,seasparam)env = jinja2.Environment(loader=jinja2.FileSystemLoader('./'))template = env.get_template('conditional-text.rst')string=template.render(public=user)print(string)else:print('Please indicate public and season')