2

I have a document containing a list of files. What is simple way to extract filenames inside the href element (without quotes)and copy them into the list separated by line breaks?

<manifest>
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
<item id="css" href="845214570.css" media-type="text/css"/>
<item id="cover-image" href="845214570.jpg" media-type="image/jpeg"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
<item id="cover" href="cover.xhtml" media-type="application/xhtml+xml"/>
<item id="author" href="author.xhtml" media-type="application/xhtml+xml"/>
<item id="title" href="title.xhtml" media-type="application/xhtml+xml"/>
<item id="copy" href="copy.xhtml" media-type="application/xhtml+xml"/>
<item id="contents" href="contents.xhtml" media-type="application/xhtml+xml"/>
<item id="preface" href="preface.xhtml" media-type="application/xhtml+xml"/>
<item id="ack" href="ack.xhtml" media-type="application/xhtml+xml"/>
<item id="ch1" href="ch1.xhtml" media-type="application/xhtml+xml"/>
<item id="ch2" href="ch2.xhtml" media-type="application/xhtml+xml"/>
<item id="ch3" href="ch3.xhtml" media-type="application/xhtml+xml"/>
<item id="ch4" href="ch4.xhtml" media-type="application/xhtml+xml"/>
<item id="ch5" href="ch5.xhtml" media-type="application/xhtml+xml"/>
<item id="ch6" href="ch6.xhtml" media-type="application/xhtml+xml"/>
<item id="ch7" href="ch7.xhtml" media-type="application/xhtml+xml"/>
<item id="ch8" href="ch8.xhtml" media-type="application/xhtml+xml"/>
<item id="ch9" href="ch9.xhtml" media-type="application/xhtml+xml"/>
<item id="ch10" href="ch10.xhtml" media-type="application/xhtml+xml"/>
<item id="ch11" href="ch11.xhtml" media-type="application/xhtml+xml"/>
<item id="app" href="app.xhtml" media-type="application/xhtml+xml"/>
<item id="appb" href="appb.xhtml" media-type="application/xhtml+xml"/>
<item id="appc" href="appc.xhtml" media-type="application/xhtml+xml"/>
<item id="index" href="index.xhtml" media-type="application/xhtml+xml"/>
<item id="img-f0019-01" href="f0019-01.jpg" media-type="image/jpeg"/>
<item id="img-f0027-01" href="f0027-01.jpg" media-type="image/jpeg"/>
<item id="img-f0029-01" href="f0029-01.jpg" media-type="image/jpeg"/>
</manifest>

1 Answer 1

6

For an XML file with this simple format, you can use grep:

grep -Po 'href="\K[^"]*' file.xml > filenames.lst

However, if you had a more complex xml, you could and should prefer a proper xml parser, e.g. xmlstarlet:

xmlstarlet sel -t -v '//item/@href' -n file.xml > filenames.lst

This can be installed via

sudo apt install xmlstarlet

As you have tagged your question with python, of course you can also use that:

#!/usr/bin/env python3
import xml.etree.ElementTree as ET
root = ET.parse('file.xml')
for item in root.findall('.//item'):
    print(item.attrib['href'])
5
  • The grep works just fine. Thank you.
    – minto
    Commented Sep 21, 2021 at 15:00
  • for python(I have python 2.x), it show error ./extract.py ./extract.py:4: FutureWarning: This search is broken in 1.3 and earlier, and will be fixed in a future version. If you rely on the current behaviour, change it to './/item' for item in root.findall('//item'): I changed, but no any output printed.
    – minto
    Commented Sep 21, 2021 at 15:12
  • I changed that to be compatible with older version of python.
    – pLumo
    Commented Sep 21, 2021 at 15:16
  • Another option I discovered recently is xq from the yq suite which enables JSON-like queries on xml documents ex. xq -r '.manifest.item[] | ."@href"' file.xml Commented Sep 21, 2021 at 16:18
  • ...or hxselect -s \\n -c 'item::attr(href)' < file.xml from the html-xml-utils package.
    – user986805
    Commented Sep 21, 2021 at 19:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .