Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F61128561
myxmlwriter.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, May 4, 17:30
Size
9 KB
Mime Type
text/x-python
Expires
Mon, May 6, 17:30 (2 d)
Engine
blob
Format
Raw Data
Handle
17469389
Attached To
rNIETZSCHEPYTHON nietzsche-python
myxmlwriter.py
View Options
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" This program can be used to pretty-write a xml string to a xml file.
"""
# Copyright (C) University of Basel 2019 {{{1
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/> 1}}}
import
inspect
import
xml.dom.minidom
as
MD
import
xml.etree.ElementTree
as
ET
import
lxml.etree
as
LET
from
datetime
import
datetime
from
rdflib
import
URIRef
from
os
import
makedirs
from
os.path
import
sep
,
basename
,
dirname
,
isfile
import
sys
import
shutil
import
warnings
sys
.
path
.
append
(
'svgscripts'
)
from
datatypes.page
import
FILE_TYPE_SVG_WORD_POSITION
,
FILE_TYPE_XML_MANUSCRIPT
__author__
=
"Christian Steiner"
__maintainer__
=
__author__
__copyright__
=
'University of Basel'
__email__
=
"christian.steiner@unibas.ch"
__status__
=
"Development"
__license__
=
"GPL v3"
__version__
=
"0.0.1"
FILE_TYPE_SVG_WORD_POSITION
=
FILE_TYPE_SVG_WORD_POSITION
FILE_TYPE_XML_MANUSCRIPT
=
FILE_TYPE_XML_MANUSCRIPT
FILE_TYPE_XML_DICT
=
'xml-dictionary'
def
attach_dict_to_xml_node
(
dictionary
,
xml_node
):
"""Create a xml tree from a dictionary.
"""
for
key
in
dictionary
.
keys
():
elem_type
=
type
(
dictionary
[
key
])
if
elem_type
!=
dict
:
node
=
LET
.
SubElement
(
xml_node
,
key
,
attrib
=
{
'type'
:
elem_type
.
__name__
})
node
.
text
=
str
(
dictionary
[
key
])
else
:
attach_dict_to_xml_node
(
dictionary
[
key
],
LET
.
SubElement
(
xml_node
,
key
))
def
copy_to_bak_dir
(
source_file
:
str
,
bak_dir
=
'./bak'
):
"""Copy file to bakup directory.
"""
date_string
=
datetime
.
now
()
.
strftime
(
'%Y-%m-
%d
_%H:%M:%S'
)
makedirs
(
bak_dir
,
exist_ok
=
True
)
target_file
=
bak_dir
+
sep
+
basename
(
source_file
)
+
'_'
+
date_string
shutil
.
copy
(
source_file
,
target_file
)
def
dict2xml
(
dictionary
,
target_file_name
):
"""Write dict 2 xml.
"""
xml_tree
=
LET
.
ElementTree
(
LET
.
Element
(
'root'
))
attach_dict_to_xml_node
(
dictionary
,
LET
.
SubElement
(
xml_tree
.
getroot
(),
'dict'
))
write_pretty
(
xml_element_tree
=
xml_tree
,
file_name
=
target_file_name
,
\
script_name
=
inspect
.
currentframe
()
.
f_code
.
co_name
,
file_type
=
FILE_TYPE_XML_DICT
)
def
get_dictionary_from_node
(
node
):
"""Return dictionary from node.
:return: dict
"""
new_dict
=
{}
if
len
(
node
.
getchildren
())
>
0
:
new_dict
.
update
({
node
.
tag
:
{}
})
for
child_node
in
node
.
getchildren
():
new_dict
.
get
(
node
.
tag
)
.
update
(
get_dictionary_from_node
(
child_node
))
else
:
elem_cls
=
eval
(
node
.
get
(
'type'
))
if
bool
(
node
.
get
(
'type'
))
else
str
value
=
elem_cls
(
node
.
text
)
if
bool
(
node
.
text
)
else
None
new_dict
.
update
({
node
.
tag
:
value
})
return
new_dict
def
lock_xml_tree
(
xml_element_tree
,
**
locker_dict
):
"""Lock xml_element_tree.
"""
if
xml_element_tree
is
not
None
and
not
test_lock
(
xml_element_tree
,
silent
=
True
):
message
=
locker_dict
.
get
(
'message'
)
if
bool
(
locker_dict
.
get
(
'message'
))
else
''
reference_file
=
locker_dict
.
get
(
'reference_file'
)
if
bool
(
locker_dict
.
get
(
'reference_file'
))
else
''
metadata
=
xml_element_tree
.
xpath
(
'./metadata'
)[
0
]
\
if
len
(
xml_element_tree
.
xpath
(
'./metadata'
))
>
0
\
else
LET
.
SubElement
(
xml_element_tree
.
getroot
(),
'metadata'
)
lock
=
LET
.
SubElement
(
metadata
,
'lock'
)
LET
.
SubElement
(
lock
,
'reference-file'
)
.
text
=
reference_file
if
message
!=
''
:
LET
.
SubElement
(
lock
,
'message'
)
.
text
=
message
def
parse_xml_of_type
(
xml_source_file
,
file_type
):
"""Return a xml_tree from xml_source_file is file is of type file_type.
"""
parser
=
LET
.
XMLParser
(
remove_blank_text
=
True
)
xml_tree
=
LET
.
parse
(
xml_source_file
,
parser
)
if
not
xml_has_type
(
file_type
,
xml_tree
=
xml_tree
):
msg
=
'File {} is not of type {}!'
.
format
(
xml_source_file
,
file_type
)
raise
Exception
(
msg
)
return
xml_tree
def
test_lock
(
xml_element_tree
=
None
,
silent
=
False
):
"""Test if xml_element_tree is locked and print a message.
:return: True if locked
"""
if
xml_element_tree
is
None
:
return
False
if
len
(
xml_element_tree
.
findall
(
'./metadata/lock'
))
>
0
:
reference_file
=
xml_element_tree
.
findall
(
'./metadata/lock/reference-file'
)
message
=
xml_element_tree
.
findall
(
'./metadata/lock/message'
)
if
not
silent
:
warning_msg
=
'File {0} is locked!'
.
format
(
xml_element_tree
.
docinfo
.
URL
)
if
len
(
reference_file
)
>
0
:
warning_msg
=
warning_msg
.
replace
(
'!'
,
' '
)
+
'on {0}.'
.
format
(
reference_file
[
0
]
.
text
)
if
len
(
message
)
>
0
:
warning_msg
=
warning_msg
+
'
\n
{0}'
.
format
(
message
[
0
]
.
text
)
warnings
.
warn
(
warning_msg
)
return
True
return
False
def
update_metadata
(
xml_element_tree
,
script_name
,
file_type
=
None
):
"""Updates metadata of xml tree.
"""
if
len
(
xml_element_tree
.
getroot
()
.
findall
(
'./metadata'
))
>
0
:
if
len
(
xml_element_tree
.
getroot
()
.
find
(
'./metadata'
)
.
findall
(
'./modifiedBy[@script="{}"]'
.
format
(
script_name
)))
==
0
:
LET
.
SubElement
(
xml_element_tree
.
getroot
()
.
find
(
'./metadata'
),
'modifiedBy'
,
attrib
=
{
'script'
:
script_name
})
xml_element_tree
.
getroot
()
.
find
(
'./metadata'
)
.
findall
(
'./modifiedBy[@script="{}"]'
.
format
(
script_name
))[
0
]
.
text
=
\
datetime
.
now
()
.
strftime
(
'%Y-%m-
%d
%H:%M:%S'
)
else
:
metadata
=
LET
.
SubElement
(
xml_element_tree
.
getroot
(),
'metadata'
)
if
file_type
is
not
None
:
LET
.
SubElement
(
metadata
,
'type'
)
.
text
=
file_type
createdBy
=
LET
.
SubElement
(
metadata
,
'createdBy'
)
LET
.
SubElement
(
createdBy
,
'script'
)
.
text
=
script_name
LET
.
SubElement
(
createdBy
,
'date'
)
.
text
=
datetime
.
now
()
.
strftime
(
'%Y-%m-
%d
%H:%M:%S'
)
def
write_backup
(
xml_element_tree
:
LET
.
ElementTree
,
file_type
=
None
,
bak_dir
=
'./bak'
)
->
str
:
"""Back up a xml_source_file.
:return: target_file_name
"""
date_string
=
datetime
.
now
()
.
strftime
(
'%Y-%m-
%d
_%H:%M:%S'
)
makedirs
(
bak_dir
,
exist_ok
=
True
)
target_file_name
=
bak_dir
+
sep
+
basename
(
xml_element_tree
.
docinfo
.
URL
)
+
'_'
+
date_string
reference_file
=
xml_element_tree
.
docinfo
.
URL
write_pretty
(
xml_element_tree
=
xml_element_tree
,
file_name
=
target_file_name
,
\
script_name
=
__file__
+
'({0},{1})'
.
format
(
inspect
.
currentframe
()
.
f_code
.
co_name
,
reference_file
),
\
file_type
=
file_type
)
return
target_file_name
def
write_pretty
(
xml_string
=
None
,
xml_element_tree
=
None
,
file_name
=
None
,
script_name
=
None
,
backup
=
False
,
file_type
=
None
,
**
locker_dict
):
"""Writes a xml string pretty to a file.
"""
if
not
bool
(
xml_string
)
and
not
bool
(
xml_element_tree
):
raise
Exception
(
"write_pretty needs a string or a xml.ElementTree!"
)
if
not
test_lock
(
xml_element_tree
):
if
len
(
locker_dict
)
>
0
and
bool
(
locker_dict
.
get
(
'reference_file'
)):
lock_xml_tree
(
xml_element_tree
,
**
locker_dict
)
if
script_name
is
not
None
and
xml_element_tree
is
not
None
:
update_metadata
(
xml_element_tree
,
script_name
,
file_type
=
file_type
)
if
file_name
is
None
and
xml_element_tree
is
not
None
\
and
xml_element_tree
.
docinfo
is
not
None
and
xml_element_tree
.
docinfo
.
URL
is
not
None
:
file_name
=
xml_element_tree
.
docinfo
.
URL
if
file_name
is
None
:
raise
Exception
(
"write_pretty needs a file_name or a xml.ElementTree with a docinfo.URL!"
)
if
backup
and
xml_element_tree
is
not
None
:
write_backup
(
xml_element_tree
,
file_type
=
file_type
)
dom
=
MD
.
parseString
(
xml_string
)
if
(
bool
(
xml_string
))
else
MD
.
parseString
(
ET
.
tostring
(
xml_element_tree
.
getroot
()))
f
=
open
(
file_name
,
"w"
)
dom
.
writexml
(
f
,
addindent
=
"
\t
"
,
newl
=
'
\n
'
,
encoding
=
'utf-8'
)
f
.
close
()
def
xml2dict
(
xml_source_file
):
"""Create dict from xml_source_file of Type FILE_TYPE_XML_DICT.
:return: dict
"""
new_dict
=
{}
xml_tree
=
LET
.
parse
(
xml_source_file
)
if
xml_has_type
(
FILE_TYPE_XML_DICT
,
xml_tree
=
xml_tree
)
\
and
len
(
xml_tree
.
xpath
(
'/root/dict'
))
>
0
:
for
node
in
xml_tree
.
xpath
(
'/root/dict'
)[
0
]
.
getchildren
():
new_dict
.
update
(
get_dictionary_from_node
(
node
))
else
:
msg
=
'File {} is not of type {}!'
.
format
(
xml_source_file
,
FILE_TYPE_XML_DICT
)
raise
Exception
(
msg
)
return
new_dict
def
xml_has_type
(
file_type
,
xml_source_file
=
None
,
xml_tree
=
None
):
"""Return true if xml_source_file/xml_tree has file type == file_type.
"""
if
xml_tree
is
None
and
xml_source_file
is
None
:
return
False
if
xml_tree
is
None
and
isfile
(
xml_source_file
):
xml_tree
=
LET
.
parse
(
xml_source_file
)
if
len
(
xml_tree
.
xpath
(
'//metadata/type/text()'
))
<
1
:
return
False
return
xml_tree
.
xpath
(
'//metadata/type/text()'
)[
0
]
==
file_type
Event Timeline
Log In to Comment