3

この質問は、以前の質問の補足です。さらに背景が必要な場合は、元の質問をここで確認できます。

lxml xpath コマンドから取得したデータを使用して Python リストに入力します。

@ ihor-kaharlichenko の優れた提案(元の質問から)を修正したコードに組み込みました。

from lxml import etree as ET
from datetime import datetime

xmlDoc = ET.parse('http://192.168.1.198/Bench_read_scalar.xml')

response = xmlDoc.getroot()
tags = (
'address',
'status',
'flow',
'dp',
'inPressure',
'actVal',
'temp',
'valveOnPercent',
)

dmtVal = []

for dmt in response.iter('dmt'):
    val = [str(dmt.xpath('./%s/text()' % tag)) for tag in tags]
    val.insert(0, str(datetime.now())) #Add timestamp at beginning of each record
    dmtVal.append(val)

for item in dmtVal:
    str(item).strip('[')
    str(item).strip(']')
    str(item).strip('"')

この最後のブロックは、私が問題を抱えている場所です。私が取得しているデータはdmtVal次のようになります。

[['2012-08-16 12:38:45.152222', "['0x46']", "['0x32']", "['1.234']", "['5.678']", "['9.123']", "['4.567']", "['0x98']", "['0x97']"], ['2012-08-16 12:38:45.152519', "['0x47']", "['0x33']", "['8.901']", "['2.345']", "['6.789']", "['0.123']", "['0x96']", "['0x95']"]]

ただし、データを次のように表示したいのです。

[['2012-08-16 12:38:45.152222', '0x46', '0x32', '1.234', '5.678', '9.123', '4.567', '0x98', '0x97'], ['2012-08-16 12:38:45.152519', '0x47', '0x33', '8.901', '2.345', '6.789', '0.123', '0x96', '0x95']]

これはかなり単純な文字列ストリッピング ジョブだと思い、元のイテレーション(dmtVal最初に入力された場所)内でコードを試しましたが、うまくいかなかったため、上記のようにループの外でストリッピング操作を行いました。まだ動作していません。私はある種のnoob-errorを作っていると思っていますが、それを見つけることができません。どんな提案でも大歓迎です!


迅速かつ有用な回答をくださった皆様に感謝します。修正されたコードは次のとおりです。

from lxml import etree as ET
from datetime import datetime

xmlDoc = ET.parse('http://192.168.1.198/Bench_read_scalar.xml')

print '...Starting to parse XML nodes'

response = xmlDoc.getroot()

tags = (
'address',
'status',
'flow',
'dp',
'inPressure',
'actVal',
'temp',
'valveOnPercent',
)

dmtVal = []

for dmt in response.iter('dmt'):
    val = [' '.join(dmt.xpath('./%s/text()' % tag)) for tag in tags]
    val.insert(0, str(datetime.now())) #Add timestamp at beginning of each record
    dmtVal.append(val)

どちらが得られますか:

...Starting to parse XML nodes
[['2012-08-16 14:41:10.442776', '0x46', '0x32', '1.234', '5.678', '9.123', '4.567', '0x98', '0x97'], ['2012-08-16 14:41:10.443052', '0x47', '0x33', '8.901', '2.345', '6.789', '0.123', '0x96', '0x95']]
...Done

みんな、ありがとう!

4

5 に答える 5

2

現在のデータを次のように指定しますgrps

解決策1-ast.literal_eval

import ast
grps = [['2012-08-16 12:38:45.152222', "['0x46']", "['0x32']", "['1.234']", "['5.678']", "['9.123']", "['4.567']", "['0x98']", "['0x97']"], ['2012-08-16 12:38:45.152519', "['0x47']", "['0x33']", "['8.901']", "['2.345']", "['6.789']", "['0.123']", "['0x96']", "['0x95']"]]
desired_output = [[grp[0]] + [ast.literal_eval(item)[0] for item in grp[1:]] for grp in grps]

print desired_output

出力

[['2012-08-16 12:38:45.152222', '0x46', '0x32', '1.234', '5.678', '9.123', '4.567', '0x98', '0x97'], ['2012-08-16 12:38:45.152519', '0x47', '0x33', '8.901', '2.345', '6.789', '0.123', '0x96', '0x95']]

説明

ast.literal_evalは安全な方法ですeval。データ型(文字列、数値、タプル、リスト、dict、ブール値、およびなし)を評価する場合にのみ機能します。あなたの場合、「['1.0']」は長さ1のリストであると評価されます['1.0']。あなたはおそらく見て、リスト内包を理解していることを確認したいと思うでしょう。

これを書く別の方法は次のとおりです。

desired_output = []
for grp in grps:  # loop through each group
    new_grp = grp[0]  # assign the first element (an array) to be our new_grp
    for item in grp[1:]  # loop over every item from index 1 to the end
        evaluated_item = ast.literal_eval(item)  # get the evaluated data
        new_grp.append(evaluated_item[0])  # append the item in the 1 item list to the new_grp
    desired_output.append(new_grp)  # append the new_grp to the desired_output list

解決策2-正規表現

import re
stripper = re.compile("[\[\]']")
grps = [['2012-08-16 12:38:45.152222', "['0x46']", "['0x32']", "['1.234']", "['5.678']", "['9.123']", "['4.567']", "['0x98']", "['0x97']"], ['2012-08-16 12:38:45.152519', "['0x47']", "['0x33']", "['8.901']", "['2.345']", "['6.789']", "['0.123']", "['0x96']", "['0x95']"]]
desired_output = [[grp[0]] + [ stripper.sub('', item) for item in grp[1:]] for grp in grps]

ソリューションの問題は、forループで繰り返される項目が参照によって渡されないため、それらを変更しても元のデータに影響がないことです。

解決策3-元のコードを修正する

ソリューションを修正するには、次のようにします。

for i, grp in enumerate(dmtVal):  # loop over the inner lists
    for j, item in enumerate(grp):
        dmtVal[i][j] = item.strip('\]')
        dmtVal[i][j] = dmtVal[i][j].lstrip('\[')
        dmtVal[i][j] = dmtVal[i][j].strip("'")

ストリップするたびにbaluebalueを割り当てる代わりにdmtVal[i][j]、逆参照された値を使用してitem操作しdmtVal[i][j]、最後に割り当てることができます。

for i, grp in enumerate(dmtVal):  # loop over the inner lists
    for j, item in enumerate(grp):
        # Could intead be
        item = item.strip('\]')
        item = dmtVal[i][j].lstrip('\[')
        item = dmtVal[i][j].strip("'")
        dmtVal[i][j] = item

またはより良い解決策(imho):

for i, grp in enumerate(dmtVal):  # loop over the inner lists
    for j, item in enumerate(grp):
        dmtVal[i][j] = item.replace('[', '').replace(']', '').replace("'", '')
于 2012-08-16T19:41:33.610 に答える
1

string.strip先頭と末尾の文字のみを取り除きます。string.replace代わりに使用することもできます。また、string.strip(および) は文字列のコピーstring.replaceを返すことに注意してください。

または''.join()、代わりに使用しstrて、ストリッピング ビジネス全体を完全に放棄します。

val = [''.join(dmt.xpath('./%s/text()' % tag)) for tag in tags]

datetime.isoformat補足として、おそらくあまりにも代わりに使用したいでしょうstr

val.insert(0, datetime.now().isoformat()) #Add timestamp at beginning of each record

help(datetime)その他のオプションについては、 を参照してください

于 2012-08-16T20:59:30.120 に答える
1

元の投稿の文字列はどこxmlにありますか... (これはある意味で両方をカバーしていると思います...)

from lxml import etree
from datetime import datetime
from ast import literal_eval

tree = etree.fromstring(xml).getroottree()
dmts = []
for dmt in tree.iterfind('dmt'):
    to_add = {'datetime': datetime.now()}
    to_add.update( {n.tag:literal_eval(n.text) for n in dmt} )
    dmts.append(to_add)

後でノードを明示的に注文することもできます-ただし、インデックス作成ではなく名前を使用できるため、このアプローチはより明確です(ただし、これはすべて、ノードの導入または削除がエラーになるかどうかによって異なります)

于 2012-08-16T21:02:12.840 に答える
1

答えは、最初から文字列を作成しないことです。


あなたの問題はコードのこの部分にあります:

for dmt in response.iter('dmt'):
    val = [str(dmt.xpath('./%s/text()' % tag)) for tag in tags]

str()ここで、リストの戻り値から文字列を抽出しようとしたと思いxpath()ます。
ただし、これは得られるものではありません。str()リストの文字列表現を提供するだけです。

やりたいことをやるには、いくつかの選択肢があります。
ただし、html を解析しているため、リストに含まれる要素の数を確実に知ることができない場合、最良のオプションはおそらく次を使用すること''.join()です。

for dmt in response.iter('dmt'):
    val = [''.join(dmt.xpath('./%s/text()' % tag)) for tag in tags]



編集:このコードを使用する場合、最後のループは必要ありません。

于 2012-08-16T20:33:16.890 に答える
1

これはあなたが必要とすることをしますが、おそらく最も空想的な方法ではありません:

new_dmt_val = []
for sublist in dmtVal:
    new_dmt_val.append([elem.strip('[\'').strip('\']') for elem in sublist])

読みやすくしようとしましたが、おそらくより少ない行で実行できますが、より紛らわしい行です。

于 2012-08-16T19:59:41.607 に答える