首页 > 解决方案 > 熊猫 read_xml 缺少数据

问题描述

我曾尝试使用 Pandas read_xml,它可以很好地读取大部分 XML,但它会遗漏一些部分,因为它的格式略有不同。我在下面包含了一个摘录,它显示“类型”、“激活”很好,但不适用于“Amt”值。它选择列标题“Amt”而不是值。谁能指出我如何阅读它的正确方向。谢谢

<Type>PYI</Type>
<Activation>N</Activation>
<Amt val="4000" curr="GBP"/>

xml_df = pd.read_xml(xml_data)

任何能够帮助我的人都尝试过阅读 Pandas.read_xml 的文档,但我可以明白为什么它不会选择这个?

标签: pythonpandasxmlreadxml

解决方案


默认情况下,pandas.read_xml解析一组节点的所有直接后代,包括其子节点和属性。除非,xpath论据表明,read_xml不会比直接后代更进一步。

为了说明您的用例。<Type>下面可能是您的 XML where及其兄弟的通用设置 ,<Activation>并被<Amt>解析。但是,<Amt>不包含文本节点,仅包含属性。所以该列中的值应该为空。

<root>
  <row>
    <Type>PYI</Type>              <!-- Type IS A CHILD NODE OF row -->
    <Activation>N</Activation>    <!-- Activation IS A CHILD NODE OF row -->
    <Amt val="4000" curr="GBP"/>  <!-- Amt IS A CHILD NODE OF row -->
  </row>
</root>

但后来你问,为什么read_xml忽略了valcurr属性?因为每个都不是<row>. 他们是<Amt>(即 的孙子<row>)的后代。如果属性被移动到<row>,那么它们将被捕获,如下所示:

<root>
  <row val="4000" curr="GBP">     <!-- val AND curr ARE CHILD ATTRIBS OF row -->
    <Type>PYI</Type>              <!-- Type IS A CHILD NODE OF row -->
    <Activation>N</Activation>    <!-- Activation IS A CHILD NODE OF row -->
    <Amt/>                        <!-- Amt IS A CHILD NODE OF row -->
  </row>
</root>

要捕获这些属性,请调整xpath参数以指向其直接父级:

amt_df = pd.read_xml("Input.xml", xpath="//Amt")

要使用<row>级别信息捕获此类属性,请考虑使用专用语言XSLT将原始 XML 转换为以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <row>
      <Type>PYI</Type>
      <Activation>N</Activation>
      <Amt_val>4000</Amt_val>
      <Amt_curr>GBP</Amt_curr>
   </row>
</root>

上面是read_xml使用stylesheet参数时解析的中间输出,如下所示:

xsl = '''<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>
  
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  
    <xsl:template match="row">
    <xsl:copy>
      <xsl:copy-of select="*[name() != 'Amt']"/>
      <Amt_val><xsl:value-of select="Amt/@val"/></Amt_val>
      <Amt_curr><xsl:value-of select="Amt/@curr"/></Amt_curr>
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>'''

row_df = pd.read_xml("Input.xml", xpath="//row", stylesheet=xsl")

推荐阅读