How to pass some variable values to RML file in Python? - python

Given an RML template, used to generate PDF file in python, how can one use variables declared in a Python script in the RML template file?
def create_pdf:
name = "My Name"
with open('/file.rml') as rml:
data = rml.read()
pdf = rml2pdf.parseString(data)
with open(f"/newpdf.pdf", 'wb') as output:
output.write(pdf.read())
return HttpResponse(status=200)
Here is the template file.rml:
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<!DOCTYPE document SYSTEM "rml_1_0.dtd">
<document filename="file.rml">
.....
<story>
<para style="h1-center">[[name]]</para> <!-- Name value should appear here -->
</story>
</document>
So how do I get the name variable value in the template?

You may preprocess your file with genshi:
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<!DOCTYPE document SYSTEM "rml_1_0.dtd">
<document xmlns:py="http://genshi.edgewall.org/" filename="file.rml">
.....
<story>
<para style="h1-center" py:content="name" /> <!-- Name value should appear here -->
</story>
</document>
Genshi template > RML file > PDF
https://genshi.readthedocs.io/en/latest/templates/

Related

Adding XML file to the last element of existing XML using Python

I have a XML file like this, let's name is XML_old:
<?xml version="1.0" encoding="UTF-8"?>
<!--
// Description : ahbbus12alda.xml
// modifications; this notice must be included on any copy.
-->
<ipxact:component xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ipxact="http://www.accellera.org/XMLSchema/IPXACT/1685-2014"
xsi:schemaLocation="http://www.accellera.org/XMLSchema/IPXACT/1685-2014
http://www.accellera.org/XMLSchema/IPXACT/1685-2014/index.xsd">
<ipxact:vendor>spiritconsortium.org</ipxact:vendor>
<ipxact:library>Leon2RTL</ipxact:library>
<ipxact:name>ahbbus12</ipxact:name>
<ipxact:version>1.3</ipxact:version>
<ipxact:busInterfaces>
<ipxact:busInterface>
<ipxact:name>AHBClk</ipxact:name>
</ipxact:busInterface>
</ipxact:busInterfaces>
</ipxact:component>
Also, I have another XML file, XML_1, like:
<?xml version="1.0" encoding="UTF-8"?>
<ipxact:component1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ipxact="http://www.accellera.org/XMLSchema/IPXACT/1685-2014"
xsi:schemaLocation="http://www.accellera.org/XMLSchema/IPXACT/1685-2014
http://www.accellera.org/XMLSchema/IPXACT/1685-2014/index.xsd">
<ipxact:vendor1>spiritconsortium.org</ipxact:vendor1>
<ipxact:library1>Leon2RTL</ipxact:library1>
<ipxact:name1>ahbbus34</ipxact:name1>
<ipxact:version1>1.3</ipxact:version1>
<ipxact:busInterfaces1>
<ipxact:busInterface1>
<ipxact:name1>AHBClk</ipxact:name1>
<ipxact:busInterface1>
<ipxact:busInterfaces1>
</ipxact:component1>
I want to add XML_1 to the XML_old as a last child of component element in XML_old file and create a new XML file like
<?xml version="1.0" encoding="UTF-8"?>
<!--
// Description : ahbbus12alda.xml
// modifications; this notice must be included on any copy.
-->
<ipxact:component xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ipxact="http://www.accellera.org/XMLSchema/IPXACT/1685-2014"
xsi:schemaLocation="http://www.accellera.org/XMLSchema/IPXACT/1685-2014
http://www.accellera.org/XMLSchema/IPXACT/1685-2014/index.xsd">
<ipxact:vendor>spiritconsortium.org</ipxact:vendor>
<ipxact:library>Leon2RTL</ipxact:library>
<ipxact:name>ahbbus12</ipxact:name>
<ipxact:version>1.3</ipxact:version>
<ipxact:busInterfaces>
<ipxact:busInterface>
<ipxact:name>AHBClk</ipxact:name>
</ipxact:busInterface>
</ipxact:busInterfaces>
<ipxact:component1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ipxact="http://www.accellera.org/XMLSchema/IPXACT/1685-2014"
xsi:schemaLocation="http://www.accellera.org/XMLSchema/IPXACT/1685-2014
http://www.accellera.org/XMLSchema/IPXACT/1685-2014/index.xsd">
<ipxact:vendor1>spiritconsortium.org</ipxact:vendor1>
<ipxact:library1>Leon2RTL</ipxact:library1>
<ipxact:name1>ahbbus34</ipxact:name1>
<ipxact:version1>1.3</ipxact:version1>
<ipxact:busInterfaces1>
<ipxact:busInterface1>
<ipxact:name1>AHBClk</ipxact:name1>
<ipxact:busInterface1>
<ipxact:busInterfaces1>
</ipxact:component1>
</ipxact:component>
I wonder how can I do this? I appreciate if you can help me.

python lxml external entity does not read file names in a directory (file:///), but will grab file (file:///home/text.txt)

I am using python 2.7 with lxml:
parser = etree.XMLParser(load_dtd=True, no_network=False, resolve_entities=True)
xml = etree.parse(data, parser=parser)
The resulting xml will parse data with external entities. It will grab files if the external entity is:
file:///home/text.txt
However, if we want the external entity to be processed to list the files in a directory:
file:///home/
the external entity variable is blank.
This is a debian machine.
Example that gets a file:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlset [
<!ENTITY list SYSTEM "file:///home/test.txt" >]>
<test>
<game>
<files>&list;</files>
</game>
</test>
Example that DOES NOT get a list of file names:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlset [
<!ENTITY list SYSTEM "file:///home/" >]>
<test>
<game>
<files>&list;</files>
</game>
</test>

trying to add element to xmeml format XML with xml.etree.ElementTree

There's an XML file generated video editing software, which contains all the data for clip exhange. The XML is valid for the software. The only thing it lacks is an element for fielddominance (I need to set 'upper' value there)
The hard part for me that the file structure.
Here's like this looks like:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xmeml>
<xmeml version="5">
<sequence>
<name>to_color (Resolve)</name>
<duration>121597</duration>
<rate>
<!-- ... -->
</rate>
<in>-1</in>
<out>-1</out>
<timecode>
<!-- ... -->
</timecode>
<media>
<video>
<track>
<clipitem id="983_0121_01_1_5FF70094C4A64669BC77.mov 0">
<name>983_0121_01_1_5FF70094C4A64669BC77.mov</name>
<duration>271</duration>
<rate>
<timebase>25</timebase>
<ntsc>false</ntsc>
</rate>
<start>0</start>
<end>221</end>
<enabled>true</enabled>
<in>25</in>
<out>246</out>
<file id="983_0121_01_1_5FF70094C4A64669BC77.mov 2">
<duration>271</duration>
<rate>
<!-- ... -->
</rate>
<name>983_0121_01_1_5FF70094C4A64669BC77.mov</name>
<pathurl>file://Capture2/Capture2/SHARED/DAVINCI_Render/111.mxf</pathurl>
<timecode>
<!-- ... -->
</timecode>
<media>
<video>
<duration>271</duration>
<samplecharacteristics>
<width>1920</width>
<height>1080</height>
</samplecharacteristics>
</video>
</media>
</file>
<compositemode>normal</compositemode>
<filter>
<enabled>true</enabled>
<start>0</start>
<end>271</end>
<effect>
<name>Opacity</name>
<effectid>opacity</effectid>
<effecttype>motion</effecttype>
<mediatype>video</mediatype>
<effectcategory>motion</effectcategory>
<parameter>
<name>opacity</name>
<parameterid>opacity</parameterid>
<value>100</value>
<valuemin>0</valuemin>
<valuemax>100</valuemax>
</parameter>
</effect>
</filter>
</clipitem>
</track>
<format>
<samplecharacteristics>
<!-- this is what I need to add START -->
<fielddominance>upper</fielddominance>
<!-- this is what I need to add END-->
<width>1920</width>
<height>1080</height>
<pixelaspectratio>square</pixelaspectratio>
<rate>
<!-- ... -->
</rate>
<codec>
<!-- ... -->
</codec>
</samplecharacteristics>
</format>
</video>
<audio>
<track>
<!-- ... -->
</track>
</audio>
</media>
</sequence>
</xmeml>
The element I need to add is in sequence - media - video - format - samplecharacteristics field.
But this tag also exists in sequence - media - video - track - clipitem - file - media - video - samplecharacteristics
I use xml.etree.ElementTree as a parser.
Here's what I am trying, and of course I'm doing it all wrong:
import xml.etree.ElementTree as ET
tree = ET.parse(r'\\capture2\11\in.xml')
root = tree.getroot()
fieldd = ET.Element('fielddominance')
fieldd.set('field','upper')
for tag in root.iter('samplecharacteristics'):
tag.append(fieldd)
output_file = r'\\capture2\11\new.xml'
with open(output_file, 'wb') as out:
tree.write(out, encoding='utf-8')
This adds fielddominance to every samplecharacteristics tag. And I have no idea how to set 'upper' value inside tag, not as attribute.
What I would like is to write <fielddominance>upper</fielddominance> only to format tag, but omit <track> tags
You can use ElementTree's limited XPath support to isolate the samplecharacteristics you want to modify. Also, setting the text of an element is done simply by setting its .text attribute.
Try this:
import xml.etree.ElementTree as ET
tree = ET.parse('in.xml')
fieldd = ET.Element('fielddominance')
fieldd.text = 'upper'
for tag in tree.findall("./sequence/media/video/format/samplecharacteristics"):
tag.append(fieldd)
tree.write('new.xml', "UTF-8", True)

Python: Appending children to an already created XML file's root using XML DOM

I'm totally new to XML and I'm stuck on how to append children to a root node of an already exisitng XML file using Python and XML DOM. Right now I have this script to create an output file:
from xml.dom.minidom import Document
doc = Document()
root_node = doc.createElement("notes") # Root
doc.appendChild(root_node)
object_node = doc.createElement("data") # Child
root_node.appendChild(object_node)
object_node.setAttribute("a_version", "something_v001.0001.ma") # Set attributes
object_node.setAttribute("b_user", "Me")
object_node.setAttribute("c_comment", "comment about file")
xml_file = open("C:/Temp/file_notes.xml", "w") # Append
xml_file.write(doc.toprettyxml())
xml_file.close()
This gives me an output file that looks like this:
<?xml version="1.0" ?>
<notes>
<data a_version="Me" b_user="something_v001.0001.ma" c_comment="comment about file"/>
</notes>
I'd like to append future data to this file so it will look something like this after 2 additional versions:
<?xml version="1.0" ?>
<notes>
<data a_version="something_v001.0001.ma" b_user="Me" c_comment="comment about file"/>
<data a_version="something_v001.0002.ma" b_user="You" c_comment="minor save"/>
<data a_version="something_v002.0003.ma" b_user="Them" c_comment="major save"/>
</notes>
But every attempt I make at appending data comes out like this:
<?xml version="1.0" ?>
<notes>
<data a_version="Me" b_user="something_v001.0001.ma" c_comment="comment about file"/>
</notes>
<?xml version="1.0" ?>
<notes>
<data a_version="Me" b_user="something_v001.0001.ma" c_comment="comment about file"/>
</notes>
<?xml version="1.0" ?>
<notes>
<data a_version="Me" b_user="something_v001.0001.ma" c_comment="comment about file"/>
</notes>
If anyone has any alternative methods to accomplish this task by using ElementTree that would be appreciated as well. There seem to be a lot more resources, but I'm not sure how to implement the solution with Maya. Thanks!
You haven't shown us any code demonstrating "every attempt I make at appending data". But never mind, here is how you can use ElementTree to append new elements to an existing XML file.
from xml.etree import ElementTree as ET
from xml.dom import minidom
# Assume that we have an existing XML document with one "data" child
doc = ET.parse("file_notes.xml")
root = doc.getroot()
# Create 2 new "data" elements
data1 = ET.Element("data", {"a_version": "something_v001.0002.ma",
"b_user": "You",
"c_comment": "minor save"})
data2 = ET.Element("data", {"a_version": "something_v001.0003.ma",
"b_user": "Them",
"c_comment": "major save"})
# Append the new "data" elements to the root element of the XML document
root.append(data1)
root.append(data2)
# Now we have a new well-formed XML document. It is not very nicely formatted...
out = ET.tostring(root)
# ...so we'll use minidom to make the output a little prettier
dom = minidom.parseString(out)
print dom.toprettyxml()
Output:
<?xml version="1.0" ?>
<notes>
<data a_version="Me" b_user="something_v001.0001.ma" c_comment="comment about file"/>
<data a_version="something_v001.0002.ma" b_user="You" c_comment="minor save"/>
<data a_version="something_v001.0003.ma" b_user="Them" c_comment="major save"/>
</notes>
ElementTree does not have a built-in pretty-printer, so we use minidom for that. The output contains some superfluous whitespace, but it is better than what ElementTree can provide.

Add a line to a file if it not exist using python

I have an xml file as follows:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build" ToolsVersion="4.0">
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
I want to add a line <Import Project="$(ProjectName).targets" /> between
</ImportGroup> and </Project> as follows
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build" ToolsVersion="4.0">
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<Import Project="$(ProjectName).targets" />
</Project>
If the line <Import Project="$(ProjectName).targets" /> already exists in file there is no need to add.
How can I do that?
Your question is based on lines in text files, but the input file is clearly XML, so assuming you actually want to add an Import if it doesn't exist, try this:
import xml.dom.minidom
importstring = "$(Projectname).targets"
filename = "test.xml"
tree = xml.dom.minidom.parse(filename)
Project = tree.getElementsByTagName("Project")[0]
for Import in Project.getElementsByTagName("Import"):
if Import.getAttribute("Project") == importstring:
break
else: # note this is else belongs to the for, not the if
newImport = xml.dom.minidom.Element("Import")
newImport.setAttribute("Project", importstring)
Project.appendChild(newImport)
tree.writexml(open(filename, 'w'))
Take the XML parser of your choice, parse the file, manipulate the file using the related API, write it back.

Categories