Python 解析PDML/XML并为其选择特定字段

Python 解析PDML/XML并为其选择特定字段,python,regex,xml,parsing,elementtree,Python,Regex,Xml,Parsing,Elementtree,我正在使用ElementTreeXML API,并试图用Python解析一个大的PDML(XML)文件。我试图获得一个带有特定信息字段的表格数据帧输出。以下是实际文件的子集 <?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet type="text/xsl" href="pdml2html.xsl"?> <!-- You can find pdml2html.xsl in C:\Program Files\W

我正在使用ElementTreeXML API,并试图用Python解析一个大的PDML(XML)文件。我试图获得一个带有特定信息字段的表格数据帧输出。以下是实际文件的子集

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="pdml2html.xsl"?>
<!-- You can find pdml2html.xsl in C:\Program Files\Wireshark or at https://code.wireshark.org/review/gitweb?p=wireshark.git;a=blob_plain;f=pdml2html.xsl. -->
<pdml version="0" creator="wireshark/3.2.2" time="Sun Mar 22 23:53:43 2020" capture_file="C:\Users\anyoung\AppData\Local\Temp\wireshark_Wi-Fi 2_20200322234518_a20824.pcapng">
<packet>
  <proto name="geninfo" pos="0" showname="General information" size="66">
    <field name="frame.cap_len" showname="Capture Length: 66 bytes (528 bits)" size="0" pos="0" show="66"/>
    <field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/>
    <field name="frame.cap_len" showname="Capture Length: 66 bytes (528 bits)" size="0" pos="0" show="66"/>
    <field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/>
    <field name="caplen" pos="0" show="66" showname="Captured Length" value="42" size="66"/>
    <field name="timestamp" pos="0" show="Mar 22, 2020 23:45:34.045301000 Pacific Daylight Time" showname="Captured Time" value="1584945934.045301000" size="66"/>
  </proto>
我真的很难用语法来完成上面的工作。我甚至无法得到任何接近的结果。

lxml

lxml将允许您使用XSLT转换XML文档。出于某种原因,XSLT被忽略,取而代之的是暴力编程对象。然而,在处理和转换XML数据时,我更喜欢使用XLST

如果您必须每天处理XML数据,我强烈建议您学习XSLT并定期使用它

XLST转换XML文档:packet.xsl 变量用于分隔符和行尾(EOL),便于修改

标题行和字段的模板用于在必要时重新排列或添加新字段

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text" media-type="string" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="delimiter" select="'&#x9;'"/>
    <xsl:variable name="EOL" select="'&#xA;'"/>

    <xsl:template match="/pdml/packet/proto">
        <xsl:call-template name="header-row"/>
        <xsl:apply-templates match="field"/>
    </xsl:template>

    <xsl:template match="field">
        <xsl:value-of select="@name"/>
        <xsl:value-of select="$delimiter"/>
        <xsl:value-of select="@size"/>
        <xsl:value-of select="$delimiter"/>
        <xsl:value-of select="@value"/>
        <xsl:value-of select="$EOL"/>
        <xsl:apply-templates select="*"/>
    </xsl:template>

    <xsl:template name="header-row">
        <xsl:element name="row">
            <xsl:text>field</xsl:text>
            <xsl:value-of select="$delimiter"/>
            <xsl:text>size</xsl:text>
            <xsl:value-of select="$delimiter"/>
            <xsl:text>value</xsl:text>
            <xsl:value-of select="$EOL"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

制表符分隔的输出

field   size    value
frame.cap_len   0   
frame.marked    0   
frame.cap_len   0   
frame.marked    0   
caplen  66  42
timestamp   66  1584945934.045301000

这里是另一个XSLT示例(更多用于@Kristian)

XML输入(Input.XML)


XSLT1.0(test.xsl)


Python 3

从lxml导入etree
tree=etree.parse(“input.xml”)
xslt=etree.parse(“test.xsl”)
new_tree=tree.xslt(xslt)
打印(新树)
打印输出

字段大小值
frame.cap_len 0
帧0.0
frame.cap_len 0
帧0.0
卡普兰66 42
时间戳66 1584945934.045301000

我同意XSLT是一个很好的选择,但是在输出文本时,使用
xsl:element
创建一组元素会让人感到困惑@DanielHaley,我创建XML元素只是为了允许选择XML或纯文本。这只是一个例子,回答了这个问题,为他指明了正确的方向。有很多方法可以剥猫皮……不幸的是,lxml似乎无法使用XSTL生成输出。我本来想做你做的事;然而,lxml etree.parse似乎只有在生成XML文档时才起作用。如果能看到lxml正确地使用XSLT,那就太好了。太好了!也许我应该发布一个问题,询问为什么我的示例不能与您的XSLT一起使用谢谢您@Daniel Haley,我从我两年前编写的命令行工具中获取了一段代码。该工具需要足够灵活,以生成XML或纯文本(带或不带XLST文档)。我应该和你的2号班轮一起去。干杯
./test.py
field   size    value
frame.cap_len   0   
frame.marked    0   
frame.cap_len   0   
frame.marked    0   
caplen  66  42
timestamp   66  1584945934.045301000