libxml2 and XPath - Iterate through repeating elements?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • nickheppleston@gmail.com

    libxml2 and XPath - Iterate through repeating elements?

    I'm trying to iterate through repeating elements to extract data using
    libxml2 but I'm having zero luck - any help would be appreciated.

    My XML source is similar to the following - I'm trying to extract the
    line number and product code from the repeating line elements:

    <order xmlns="some-ns">
    <header>
    <orderno>123456 </orderno>
    </header>
    <lines>
    <line>
    <lineno>1</lineno>
    <productcode>PE NS</productcode>
    </line>
    <line>
    <lineno>2</lineno>
    <productcode>ST APLER</productcode>
    </line>
    <line>
    <lineno>3</lineno>
    <productcode>RU LER</productcode>
    </line>
    </lines>
    </order>

    With the following code I can get at the non-repeating elements in the
    header, and get the lines elements, but cannot extract the
    lineno/productcode data via xpath:

    XmlDoc = libxml2.parseFi le(XmlFile);
    XPathDoc = XmlDoc.xpathNew Context();
    XPathDoc.xpathR egisterNs('so', "some-ns");


    # Extract data from the order header
    PurchaseOrderNo =
    XPathDoc.xpathE val('//so:order/so:header/so:orderno');

    # Extract data from the order lines
    for line in XPathDoc.xpathE val('//so:order/so:lines/so:line'):
    print line.content;

    # Explicitly free Xml document and XPath context
    XmlDoc.freeDoc( )
    XPathDoc.xpathF reeContext()

    Ideally, I'd like to select the line data using xpath (similar to an
    XSLT query after a 'for-each' - i.e. xpathEval('so:l ineno') and
    xpathEval('so:p roductcode') once I've got the line element).

    Any suggestions grealty appreciated!

    Cheers, Nick.

  • Paul Boddie

    #2
    Re: libxml2 and XPath - Iterate through repeating elements?

    nickhepples...@ gmail.com wrote:[color=blue]
    > I'm trying to iterate through repeating elements to extract data using
    > libxml2 but I'm having zero luck - any help would be appreciated.[/color]

    Here's how I attempt to solve the problem using libxml2dom [1] (and I
    imagine others will suggest their own favourite modules, too):

    import libxml2dom
    d = libxml2dom.pars eFile(filename)
    order_numbers = d.xpath("//so:order/so:header/so:orderno",
    namespaces={"so " : "some-ns"})

    At this point, you have a list of nodes. (I imagine that whatever
    object the libxml2 module API produces probably has those previous and
    next attributes to navigate the result list instead.) The nodes in the
    list represent the orderno elements in this case, and in libxml2dom you
    can choose to invoke the usual DOM methods on such node objects, or
    even the toString method if you want the document text. For the line
    items...

    lines = d.xpath("//so:order/so:lines/so:line", namespaces={"so " :
    "some-ns"})
    for line in lines:
    print line.toString()

    I can't remember what the libxml2 module produces for the content
    attribute of a node, although the underlying libxml2 API produces a
    "text-only" representation of the document text, as opposed to the
    actual document text that the toString method produces in the above
    example. I imagine that an application working with the line item
    information would use additional DOM or XPath processing to get the
    line item index and the product code directly.

    Anyway, I recommend libxml2dom because if you're already using the
    bundled libxml2 module, you should be able to install libxml2dom and
    plug into the same infrastructure that the bundled module depends upon.
    Moreover, libxml2dom is a "pure Python" package that doesn't require
    any extension module compilation, so it should be quite portable to
    whatever platform you're using.

    Paul

    [1] http://www.python.org/pypi/libxml2dom

    Comment

    • Jean-Roch SOTTY

      #3
      Re: libxml2 and XPath - Iterate through repeating elements?

      Le Vendredi 2 Décembre 2005 18:31, nickheppleston@ gmail.com a écrit :[color=blue]
      > I'm trying to iterate through repeating elements to extract data using
      > libxml2 but I'm having zero luck - any help would be appreciated.
      >
      > My XML source is similar to the following - I'm trying to extract the
      > line number and product code from the repeating line elements:
      >
      > <order xmlns="some-ns">
      > <header>
      > <orderno>123456 </orderno>
      > </header>
      > <lines>
      > <line>
      > <lineno>1</lineno>
      > <productcode>PE NS</productcode>
      > </line>
      > <line>
      > <lineno>2</lineno>
      > <productcode>ST APLER</productcode>
      > </line>
      > <line>
      > <lineno>3</lineno>
      > <productcode>RU LER</productcode>
      > </line>
      > </lines>
      > </order>[/color]
      The result of an xpath evaluation is a list of node, which you can perform
      another xpatheval() on :

      import libxml2
      doc = libxml2.parseFi le(XmlFile)
      root = doc.getRootElem ent()
      line_nodes = root.xpathEval( 'lines/line')
      for line_node in line_nodes:
      print line_node.xpath Eval('lineno')[0].content
      print line_node.xpath Eval('productco de')[0].content
      doc.freeDoc()

      --
      Cordially

      Jean-Roch SOTTY

      Comment

      Working...