Python-generated citygml file failed validation, although identical to example file - python

These are two citygml files:
an example file from the citygml website with some changes done to the file manually (https://drive.google.com/file/d/0Bx7bUIyq-ZEWY3FRb1hTbEU0SGc/view?usp=sharing)
one generated by my python & lxml code in an attempt to recreate the example file (https://drive.google.com/file/d/0Bx7bUIyq-ZEWaU1tNU1Wc01XNW8/view?usp=sharing)
When i open the 2 files with notepad ++ and go through them line by line, the python generated file is identical to the example file, however when I try to validate the python-generated file with the citygml xsd schema it failed, while the example file passed. Why is this the case, since they are identical, am I doing something wrong ? (I am new to dealing with xml files)
This is a snippet of my python code, the xml file built using etree (since I cant post more than two links for you to download my code):
et = ElementTree(root) cityObjectMember = SubElement(root,'cityObjectMember') luse = SubElement(cityObjectMember, "{" + XMLNamespaces.luse+ "}" +'Landuse') luse.attrib["{" + XMLNamespaces.gml+ "}" +'id'] = 'ID_ground_texture'
Thanks in advance.

Don't trust your eyes, let the computer compare the files:
$ diff -u0 landusetest_validated.gml landusetest_cnntbevalidated.gml
--- landusetest_validated.gml 2015-12-28 14:33:34.437635671 +0100
+++ landusetest_cnntbevalidated.gml 2015-12-28 14:33:34.437635671 +0100
## -4,2 +4,2 ##
- <luse:LandUse gml:id="ID_ground_texture">
- <gml:name>Simple textured patch</gml:name>
+ <luse:Landuse gml:id="ID_ground_texture">
+ <gml:name>simple textured patch</gml:name>
## -26 +26 ##
- </luse:LandUse>
+ </luse:Landuse>
Case does matter. Landuse != LandUse.

Related

reading configuration file entries with dynamic names in python

i am new to python but already programmed much in PHP. And here is my problem cause both languages use a bit different spelling and usage.
when i want to access a variable in PHP with a dynamic content i can do $array_name[$variable_name]
but how can i do this in python when i do not know the content of $variable_name?
My actual problem:
get a ini entry by variable with dynamic content. In my python script the variable "mode_name" is dynamically filled by an API request. so i do not know the content. The script is checking if this content of "mode_name" is listed in "config/modes" in the ini File. When it is listed, then there is a ini category with the same name and this should be returned in the API request. But see below the code, may be it explains it better.
i shortened the code a bit, cause everything else is working. and the dynamic var gets the correct name ("trafficlight") so it should work (in PHP) but i just getting an error.
python script:
import configparser
configfile = 'setup.ini'
config = configparser.ConfigParser()
config.read(configfile)
if mode_name in config['config']['modes']:
ret = config[mode_name]
return jsonify({'mode_name':ret})
ini file:
[config]
modes = 'trafficlight, record'
[trafficlight]
title = 'trafficlight'
lights = 'red, yellow, green'
gpio_red = 17
gpio_yellow = false
gpio_green = 18
[record]
title = 'recording'
gpio = 17
running this ends up in the following error:
File "app.py", line 6
ret = config[mode_name]
^
TabError: inconsistent use of tabs and spaces in indentation
What am doing wrong here? Thanks in advance!

Make blank tex file handle PyLatex

I want to make a blank tex file in PyLatex with no headers and no environments added from the start. i.e. I do not want \documentclass and \begin{document} to be in my LaTex file. I've tried to write a class that does not propagate any packages or adds anything to the file in the beginning, but I can no longer add my commands to the file afterward.
\cvsection{}
\begin{cventries}
\cventry
{}
{}
{}
{}
{}
\vspace{5mm}
\end{cventries}
But every I've tried to use the Document class, PyLatex adds the \begin{document} and \documentclass preamble. This is the minimum I've been able to achieve:
\documentclass
%
%
%
%
\begin{document}%
\normalsize%
\end{document}
I only need a simple blank tex file where I can add 1 command cvsection and 1 environment cventries.
This was the dumps method in my class:
def dumps(self):
head = ''
print("No headers")
head += dumps_list(self.variables) + '%\n'
head += dumps_list(self.preamble) + '%\n'
return head + '%\n' + super(ArgFreeDoc, self).dumps()
This still has the same output as the Document class. If I remove the super method in the return statement, I can't add new text to my file.
TLDR; How do I generate a blank tex file class and add commands to it after that?

Python: script that takes a text file and produces another text file with certain lines modified

I'm writing a python script that takes a text file and should produce another text file with certain lines minimally changed.
I keep getting stuck and would appreciate some assistance.
The intention is that from the commandline I can run:
$ ./script_j_to_uj.py eval_c_sensor.j eval_c_sensor.uj
and that the .uj contains the .j text with the specified changes.
My code so far is:
#!/usr/bin/env python
import os, sys
input = open(sys.argv[1])
output = open(sys.argv[2], 'w')
for s in input.xreadlines( ):
output.write(s.replace("lib_c_support", "lljvm/lib/lib_c_support"))
output.write(s.replace(".method public <clinit>()V", ".method static <clinit>()V"))
output.write(s.replace("invokestatic java/lang/lljvm/lib/c/exit(I)V", ";;;; invokestatic java/lang/lljvm/lib/c/exit(I)V"))
output.write(s.replace(".method public static main([Ljava/lang/String;)V", ".method public static main()V"))
output.write(s.replace("invokestatic eval_c_sensor/main()I", "invokestatic eval_c_sensor/main2()I"))
output.write(s.replace(".method public static main()I", ".method public static main2()I"))
output.close( )
input.close( )
But this produces errors. I believe my first mistake is in viewing the text file, but I'm not certain.
The error is:
File "C:/Users/SvenA/OneDrive/Documents/temp/script.py", line 6, in <module>
for s in input.xreadlines( ):
AttributeError: '_io.TextIOWrapper' object has no attribute 'xreadlines'
I assume you intended to write something similar to:
#!/usr/bin/env python
import os, sys
with open(sys.argv[1]) as input:
# Ensure the output file is empty
with open(sys.argv[2], 'w') as output:
output.write('')
# Write all of the lines
with open(sys.argv[2], 'a') as output:
for s in input.readlines():
output.write(s.replace("lib_c_support", "lljvm/lib/lib_c_support"
).replace(".method public <clinit>()V", ".method static <clinit>()V"
).replace("invokestatic java/lang/lljvm/lib/c/exit(I)V", ";;;; invokestatic java/lang/lljvm/lib/c/exit(I)V"
).replace(".method public static main([Ljava/lang/String;)V", ".method public static main()V"
).replace("invokestatic eval_c_sensor/main()I", "invokestatic eval_c_sensor/main2()I"
).replace(".method public static main()I", ".method public static main2()I"))
My code is still a bit of a mess, but you seemed to have three problems:
Writing 6 times instead of 1
Using 'w'rite instead of 'a'ppend as mode, and
Using xreadlines instead of readlines.

xml data gets appended to old file even if I delete the file

I have to write xml data to file and if file exists I have to remove that file first but it appends the data every time to the same file.
Note: I am doing this in scons file
myfile.py
class AttributeDataXmlBuilder():
def __init__(self, AttrXml, simAttrXml, logger = logging.getLogger(__name__)):
self.logger = logger
self.simAttrXml = os.path.join(simAttrXml, "AttributeData.xml")
self.AttrXml = AttrXml
assert len(AttrXml) > 0, 'Need at least two xml file to merge'
self.roots = [ElementTree.parse(xml_file).getroot() for xml_file in self.AttrXml]
def combine(self):
# iteratively add all files to first file
for root_tag in self.roots[1:]:
self.combine_element(self.roots[0], root_tag)
# iterate final file for readaccess and writeaccess tag and change there value to NoAccess
for read_access in self.roots[0].iter('ReadAccess'):
if read_access.text != 'NoAccess':
read_access.text = 'NoAccess'
for write_access in self.roots[0].iter('WriteAccess'):
if write_access.text != 'NoAccess':
write_access.text = 'NoAccess'
# set owner as System
self.roots[0].attrib['owner'] = 'System'
ATT_DATA = ElementTree.ElementTree(self.roots[0])
ATT_DATA.write(self.simAttrXml, encoding="utf-8", xml_declaration=True)
def combine_element(self, one, other):
one.extend(other)
SConscript
myfile.XmlBuilder(DataXml, sDataXml_loc).combine()
From the Python documentation on open:
mode is an optional string that specifies the mode in which the file is opened. It defaults to 'r' which means open for reading in text mode. Other common values are 'w' for writing (truncating the file if it already exists) ...
In plain English, this means that when you open the file for writing its existing contents are immediately deleted and whatever you write to the file (if anything) becomes its new content. You say
"if file exists I have to remove that file first"
so it looks as though the ElementTree's write method is doing something weird. I presume you have checked that the file size increases after each run, rather than a simple visual inspection of the output? I'd be very surprised if ElementTree outputs were so different from standard Python files.
EDIT: The following program creates an XML file, parses it and writes a subtree out to a new file:
from xml.etree.ElementTree import ElementTree
data = """\
<html>
<head>
<title>Example page</title>
</head>
<body>
<p>Moved to example.org
or example.com.</p>
</body>
</html>
"""
with open('input.xml', 'w') as f:
f.write(data)
tree = ElementTree()
tree.parse('input.xml')
p = tree.find("body/p") # Finds first occurrence of tag p in body
links = list(p.iter("a")) # Returns list of all links
for i in links: # Iterates through all found links
i.attrib["target"] = "blank"
tree.write("output.xhtml")
I run it once:
(static_web) Airhead:tmp sholden$ ls -l input.xml output.xhtml
-rw-r--r-- 1 sholden wheel 225 15 Mar 10:23 input.xml
-rw-r--r-- 1 sholden wheel 254 15 Mar 10:23 output.xhtml
I run it again:
(static_web) Airhead:tmp sholden$ ls -l input.xml output.xhtml
-rw-r--r-- 1 sholden wheel 225 15 Mar 10:23 input.xml
-rw-r--r-- 1 sholden wheel 254 15 Mar 10:23 output.xhtml
and the files are the same length. Not even the creation time has changed, since they have been truncated rather than removed and rewritten. You could add an os.remove call to verify it made no difference to the file sizes.

Retrieve XML parent and child attributes using Python and lxml

I'm trying to process an XML file using XPATH in Python / lxml.
I can pull out the values at a particular level of the tree using this code:
file_name = input('Enter the file name, including .xml extension: ') # User inputs file name
print('Parsing ' + file_name)
from lxml import etree
parser = etree.XMLParser()
tree = etree.parse(file_name, parser)
r = tree.xpath('/dataimport/programmelist/programme')
print (len(r))
with open(file_name+'.log', 'w', encoding='utf-8') as f:
for r in tree.xpath('/dataimport/programmelist/programme'):
progid = (r.get("id"))
print (progid)
It returns a list of values as expected. I also want to return the value of a 'child' (where it exists), but I can't work out how (I can only get it to work as a separate list, but I need to maintain the link between them).
Note: I will be writing the values out to a log file, but since I haven't been successful in getting everything out that I want, I haven't added the 'write out' code yet.
This is the structure of the XML:
<dataimport dtdversion="1.1">
<programmelist>
<programme id="eid-273168">
<imageref idref="img-1844575"/>
How can I get Python to return the id + idref?
The previous examples I have worked with had namespaces, but this file doesn't.
Since xpath() method returns tree, you can use xpath again to get idref list you want:
for r in tree.xpath('/dataimport/programmelist/programme')
progid = r.get("id")
ref_list = r.xpath('imageref/#idref')
print progid, ref_lis

Categories

Resources