Каков наилучший способ анализа списка определений с помощью XPath? - PullRequest
2 голосов
/ 11 февраля 2011

Я использую Python + xPath для разбора некоторого HTML, но у меня возникают проблемы при разборе списка определений.Пример может быть следующим:

<dl><br> <dt>Section One</dt><br> <dd>Child one</dd><br> <dd>Child one.2</dd><br> <dt>Section Two</dt><br> <dd>Child two</dd><br> </dl>

Я хочу преобразовать это в вывод, например:
{'Section One' : ['Child one','Child one.2'], 'Section Two' : ['Child two']}

У меня возникли трудности, хотя из-заКак это ни структурировано, в выходных данных нет той иерархии, которую вы найдете.

Спасибо

Ответы [ 2 ]

3 голосов
/ 11 февраля 2011

Решение без xpath, использующее lxml (которое вы, вероятно, уже используете, если используете xpath?):

from collections import defaultdict
from lxml import etree

dl = etree.fromstring('''<dl>
<dt>Section One</dt>
<dd>Child one</dd>
<dd>Child one.2</dd>
<dt>Section Two</dt>
<dd>Child two</dd>
</dl>''')

result = defaultdict(list)
for dt in dl.findall('dt'):
    for child in dt.itersiblings(): # iterate over following siblings
        if child.tag != 'dd':
            break # stop at the first element that is not a dd
        result[dt.text].append(child.text)

print dict(result)

(любое решение xpath, которое я могу придумать, хуже этого)

0 голосов
/ 11 февраля 2011

Решение XPath 1.0 с одним выражением, если вообще возможно, будет сложно написать и понять .

Вот простое решение XSLT 1.0:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:key name="kFollowing" match="dd"
      use="generate-id(preceding-sibling::dt[1])"/>

 <xsl:template match="dl">
  { <xsl:apply-templates select="dt"/> }
 </xsl:template>

 <xsl:template match="dt">
  <xsl:text/>'<xsl:value-of select="."/>' : [ <xsl:text/>
   <xsl:apply-templates select=
       "key('kFollowing', generate-id())"/>
   <xsl:text> ]</xsl:text>
   <xsl:if test="not(position()=last())">, </xsl:if>
 </xsl:template>

 <xsl:template match="dd">
  <xsl:text/>'<xsl:value-of select="."/>'<xsl:text/>
   <xsl:if test="not(position()=last())">, </xsl:if>
 </xsl:template>
</xsl:stylesheet>

, когда это преобразование применяется к предоставленному документу XML:

<dl>
    <dt>Section One</dt>
    <dd>Child one</dd>
    <dd>Child one.2</dd>
    <dt>Section Two</dt>
    <dd>Child two</dd>
</dl>

желаемый, правильный результат:

  { 'Section One' : [ 'Child one', 'Child one.2' ], 'Section Two' : [ 'Child two' ] }

Объяснение : xsl:key определено и используется для захвата отношения 1 -> много между dt и непосредственно следующими элементами родственного элемента dt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...