0

I've been beating myself trying to parse XML response from library documentation, but cannot determine a simple way to find the values I want. I'll use any common library.

Sample XML response which is in string format:

<entry
       xmlns="http://www.w3.org/2005/Atom"
       xmlns:s="http://dev.splunk.com/ns/rest"
       xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
  <title>search index</title>
  <id>https://localhost:8089/services/search/jobs/mysearch_02151949</id>
  <updated>2011-07-07T20:49:58.000-07:00</updated>
  <link href="/services/search/jobs/mysearch_02151949" rel="alternate"/>
  <published>2011-07-07T20:49:57.000-07:00</published>
  <link href="/services/search/jobs/mysearch_02151949/search.log" rel="search.log"/>
  <link href="/services/search/jobs/mysearch_02151949/events" rel="events"/>
  <link href="/services/search/jobs/mysearch_02151949/results" rel="results"/>
  <link href="/services/search/jobs/mysearch_02151949/results_preview" rel="results_preview"/>
  <link href="/services/search/jobs/mysearch_02151949/timeline" rel="timeline"/>
  <link href="/services/search/jobs/mysearch_02151949/summary" rel="summary"/>
  <link href="/services/search/jobs/mysearch_02151949/control" rel="control"/>
  <author>
    <name>admin</name>
  </author>
  <content type="text/xml">
    <s:dict>
      <s:key name="cursorTime">1969-12-31T16:00:00.000-08:00</s:key>
      <s:key name="delegate"></s:key>
      <s:key name="diskUsage">2174976</s:key>
      <s:key name="dispatchState">DONE</s:key>
      <s:key name="doneProgress">1.00000</s:key>
      <s:key name="dropCount">0</s:key>
      <s:key name="earliestTime">2011-07-07T11:18:08.000-07:00</s:key>
      <s:key name="eventAvailableCount">287</s:key>
      <s:key name="eventCount">287</s:key>
      <s:key name="eventFieldCount">6</s:key>
      <s:key name="eventIsStreaming">1</s:key>
      <s:key name="eventIsTruncated">0</s:key>
      <s:key name="eventSearch">search index</s:key>
      <s:key name="eventSorting">desc</s:key>
      <s:key name="isDone">1</s:key>

I've truncated the output and the two values I want are the text values for:

  • name="isDone" (1)
  • name="doneProgress" (1.00000)
  • name="eventCount" (287)

How do I find these numeric values?

DJimmy
  • 21
  • 3
  • Have you looked at beautifulsoup4? I've had good luck with it. For example: http://stackoverflow.com/questions/4071696/python-beautifulsoup-xml-parsing#4093940 – Tom Barron Feb 28 '17 at 23:10
  • I'm a big fan of BS4. I just wanted an actual XML library to do the work, since it's integrating with Splunk which is XML-native. – DJimmy Mar 01 '17 at 03:07

1 Answers1

1

You can use lxml and xpath:

ns = {'s':"http://dev.splunk.com/ns/rest"}
print xml.xpath("//s:key[@name='isDone']/text()", namespaces=ns)

which will print [1]. Full example:

xml = '''
<entry
       xmlns="http://www.w3.org/2005/Atom"
       xmlns:s="http://dev.splunk.com/ns/rest"
       xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
  <title>search index</title>
  <id>https://localhost:8089/services/search/jobs/mysearch_02151949</id>
  <updated>2011-07-07T20:49:58.000-07:00</updated>
  <link href="/services/search/jobs/mysearch_02151949" rel="alternate"/>
  <published>2011-07-07T20:49:57.000-07:00</published>
  <link href="/services/search/jobs/mysearch_02151949/search.log" rel="search.log"/>
  <link href="/services/search/jobs/mysearch_02151949/events" rel="events"/>
  <link href="/services/search/jobs/mysearch_02151949/results" rel="results"/>
  <link href="/services/search/jobs/mysearch_02151949/results_preview" rel="results_preview"/>
  <link href="/services/search/jobs/mysearch_02151949/timeline" rel="timeline"/>
  <link href="/services/search/jobs/mysearch_02151949/summary" rel="summary"/>
  <link href="/services/search/jobs/mysearch_02151949/control" rel="control"/>
  <author>
    <name>admin</name>
  </author>
  <content type="text/xml">
    <s:dict>
      <s:key name="cursorTime">1969-12-31T16:00:00.000-08:00</s:key>
      <s:key name="delegate"></s:key>
      <s:key name="diskUsage">2174976</s:key>
      <s:key name="dispatchState">DONE</s:key>
      <s:key name="doneProgress">1.00000</s:key>
      <s:key name="dropCount">0</s:key>
      <s:key name="earliestTime">2011-07-07T11:18:08.000-07:00</s:key>
      <s:key name="eventAvailableCount">287</s:key>
      <s:key name="eventCount">287</s:key>
      <s:key name="eventFieldCount">6</s:key>
      <s:key name="eventIsStreaming">1</s:key>
      <s:key name="eventIsTruncated">0</s:key>
      <s:key name="eventSearch">search index</s:key>
      <s:key name="eventSorting">desc</s:key>
      <s:key name="isDone">1</s:key>
    </s:dict>
  </content>
</entry>
'''

from lxml import etree
from cStringIO import StringIO

xml = StringIO(xml)
xml = etree.parse(xml)
ns = {'s':"http://dev.splunk.com/ns/rest"}
print xml.xpath("//s:key[@name='isDone']/text()", namespaces=ns)
thebjorn
  • 26,297
  • 11
  • 96
  • 138
  • My source is already in string format, so I'm able to omit `from cStringIO import StringIO` `xml = StringIO(xml)` I've tried using this: `xml = etree.fromstring(xml)` `ns = {'s':"http://dev.splunk.com/ns/rest"}` `print xml.xpath("//s:key[@name='isDone']/text()", namespaces=ns)` but now I get AttributeError: 'Element' object has no attribute xpath – DJimmy Mar 01 '17 at 00:07
  • Actually, it worked. My AttributeError problem was unrelated. – DJimmy Mar 01 '17 at 00:20