Closed molexx closed 1 year ago
Hi, thanks for reporting the bug.
Here are the steps of my analysis. First, I executed the following code to locate the XMP key that could not be modified:
import pyexiv2
img = pyexiv2.Image('test.jpg')
xmp = img.read_xmp()
for k,v in xmp.items():
print(f'"{k}": {v}')
img.modify_xmp({k: v})
Then I found this particular key:
>>> img.clear_xmp()
>>> img.modify_xmp({"Xmp.iptcExt.ArtworkOrObject": 'type="Bag"'})
>>> img.modify_xmp({"Xmp.iptcExt.ArtworkOrObject[1]": 'type="Struct"'})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
self.img.modify_xmp(self._dumps(data), encoding)
RuntimeError: XMP Toolkit error 102: Composite nodes can't have values
Failed to encode XMP metadata.
I checked the docs of exiv2. This key, which contains [1]
, is a struct that holds the sub-elements of an array.
https://exiv2.org/manpage.html#set_xmp_struct
In order to modify the key in this format, it is necessary to change
img.modify_xmp({"Xmp.iptcExt.ArtworkOrObject": 'type="Bag"'})
to
img.modify_xmp({"Xmp.iptcExt.ArtworkOrObject": ['']})
I'll release a new version of pyexiv2 that automates this conversion.
In short, this key is a special data structure used by exiv2 to read and write XMP.
You can also get the raw XMP data via img.read_raw_xmp()
, then extract its sub-elements via import lxml
or import re
.
Thank you!
I have been trying to parse the XML to edit it - I need to add elements some way down the structure and get the namespaces right which is tripping me up so I'd much prefer to not reinvent the wheel :-)
I just released pyexiv2 v2.9.0
Now when calling img.read_xmp()
, {"Xmp.iptcExt.ArtworkOrObject": 'type="Bag"'}
is automatically converted to {"Xmp.iptcExt.ArtworkOrObject": ['']}
. The this value can be entered into img.modify_xmp(??)
.
If img.modify_xmp({"Xmp.iptcExt.ArtworkOrObject": 'type="Bag"'})
is executed, it will still fail.
Ah works great, thank you!
Sometimes writing XMP metadata to an image using
modify_xmp()
raises this error:RuntimeError: XMP Toolkit error 102: Composite nodes can't have values
read_raw_xmp()
and thenmodify_raw_xmp()
works fine but I would like to edit some of the metadata in between read/modify and the dict is much more usable than trying to parse the XML and back again (during which I would probably cause more problems).This can be recreated using this snippet which uses the IPTC's example jpg with lots of metadata: