【问题标题】:put filename in file between tags <fileName></fileName>将文件名放在标签 <fileName></fileName> 之间的文件中
【发布时间】:2020-02-06 16:33:51
【问题描述】:

在将几千张 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 相同。 最好的方法是什么?我应该使用带有 find 和 sed 的 bash,还是使用带有 string.replace 的 Python,还是有更好的选择?

【问题讨论】:

    标签: python xml sed tags filenames


    【解决方案1】:

    不要不要使用字符串处理工具来处理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 expressionupdates the text 查找树中的第一个 &lt;fileName&gt; 元素(使用 filename stem,这是没有.xml 扩展名)并将 XML 树写回原始文件。

    您说您使用ALTO schema,它使用XML namespaces 来区分版本;以上应该从根元素中选择要使用的正确命名空间,然后在 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>
    

    【讨论】:

    • 它适用于你的演示,但不适用于我的文件,文件开头为:loc.gov/standards/alto/ns-v3#" xmlns:xlink="w3.org/1999/xlink" xmlns:xsi="w3.org/2001/XMLSchema-instance" xsi:schemaLocation="loc.gov/standards/alto/ns-v3# loc.gov/alto/v3/alto-3-0.xsd"> pixel文件名>
    • @Rene:那是因为你的 XML 是命名空间的,你需要在 XPath 表达式中包含它:.//{http://www.loc.gov/standards/alto/ns-v3#}fileName
    • 我在使用 lxml.de/xpathxslt.html 中的示例时遇到了命名空间问题,但我被困住了。你能说得更清楚一点吗?
    • @Rene:我一开始忘记在.write() 中包含default_namespace 参数,但在此期间已修复。
    • @Rene: 当然,把它放在命名空间注册表中,因为没有前缀也可以。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    相关资源
    最近更新 更多