将几千个TIFF图像OCR转换为ALTO XML之后,我发现xml中的文件名标记为空。 xml文件开头为:
<?xml version="1.0" encoding="UTF-8"?>
<alto xmlns="http://www.loc.gov/standards/alto/ns-v3#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/standards/alto/ns-v3# http://www.loc.gov/alto/v3/alto-3-0.xsd">
<Description>
<MeasurementUnit>pixel</MeasurementUnit>
<sourceImageInformation>
<fileName> </fileName>
</sourceImageInformation>
我想(递归)处理所有xml文件,并在标签之间添加tiff的名称。 xml的基本名称与tiff相同。 最好的方法是什么?我应该将bash与find和sed一起使用,还是将Python与string.replace一起使用,还是有更好的选择?
答案 0 :(得分:4)
不要不要使用字符串处理工具来处理XML! XML不是常规格式,使用str.replace()
或sed
或任何此类工具很可能会导致误报和错误。
使用XML解析器; Python具有xml.etree.ElementTree
,这使此任务足够简单:
from pathlib import Path
from xml.etree import ElementTree as ET
for xmlfile in Path("directory_with_xml_files").glob("*.xml"):
tree = ET.parse(xmlfile)
namespace = tree.getroot().tag.partition('}')[0][1:]
elem = tree.find(f".//a:fileName", {'a': namespace})
elem.text = f"{xmlfile.stem}.tiff"
tree.write(xmlfile, default_namespace=namespace,
encoding="UTF-8", xml_declaration=True)
以上处理给定目录中的所有XML文件(使用pathlib
module,使用Path.glob()
method查找XML文件)。对于每个文件,它将XML数据解析为XML树,并使用该元素的简单XPath expression,updates the text(使用{{3})在树中找到第一个<fileName>
元素},它是没有扩展名.xml
的基本名称),并将XML树写回到原始文件中。
您说过您使用filename stem,后者使用ALTO schema来区分版本。上面的代码应该从根元素中选择要使用的正确名称空间,然后在XPath查询中使用该名称空间(以a
作为前缀)。
演示:
$ mkdir demo
$ cat << EOF > demo/foo.xml
> <?xml version="1.0" encoding="UTF-8"?>
> <alto xmlns="http://www.loc.gov/standards/alto/ns-v3#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/standards/alto/ns-v3# http://www.loc.gov/alto/v3/alto-3-0.xsd">
> <Description>
> <MeasurementUnit>pixel</MeasurementUnit>
> <sourceImageInformation>
> <fileName> </fileName>
> </sourceImageInformation>
> </Description>
> </alto>
> EOF
$ cp demo/foo.xml demo/bar.xml
$ cp demo/foo.xml demo/baz.xml
$ python3.7
Python 3.7.4 (default, Jul 9 2019, 19:45:08)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from pathlib import Path
>>> from xml.etree import ElementTree as ET
>>> for xmlfile in Path("demo").glob("*.xml"):
... tree = ET.parse(xmlfile)
... namespace = tree.getroot().tag.partition('}')[0][1:]
... elem = tree.find(f".//a:fileName", {'a': namespace})
... elem.text = f"{xmlfile.stem}.tiff"
... tree.write(xmlfile, default_namespace=namespace,
... encoding="UTF-8", xml_declaration=True)
...
>>> ^D
$ cat demo/*.xml
<?xml version='1.0' encoding='UTF-8'?>
<alto xmlns="http://www.loc.gov/standards/alto/ns-v3#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/standards/alto/ns-v3# http://www.loc.gov/alto/v3/alto-3-0.xsd">
<Description>
<MeasurementUnit>pixel</MeasurementUnit>
<sourceImageInformation>
<fileName>bar.tiff</fileName>
</sourceImageInformation>
</Description>
</alto><?xml version='1.0' encoding='UTF-8'?>
<alto xmlns="http://www.loc.gov/standards/alto/ns-v3#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/standards/alto/ns-v3# http://www.loc.gov/alto/v3/alto-3-0.xsd">
<Description>
<MeasurementUnit>pixel</MeasurementUnit>
<sourceImageInformation>
<fileName>baz.tiff</fileName>
</sourceImageInformation>
</Description>
</alto><?xml version='1.0' encoding='UTF-8'?>
<alto xmlns="http://www.loc.gov/standards/alto/ns-v3#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/standards/alto/ns-v3# http://www.loc.gov/alto/v3/alto-3-0.xsd">
<Description>
<MeasurementUnit>pixel</MeasurementUnit>
<sourceImageInformation>
<fileName>foo.tiff</fileName>
</sourceImageInformation>
</Description>
</alto>