簡體   English   中英

R:如何根據 xml 文件中的嵌套結果擴展 data.frame

[英]R: How to expand a data.frame based on nested results in xml file

<StudyFieldsResponse>
    <StudyFieldsList>
      <StudyFields Rank="2">
      <FieldValues Field="id">
        <FieldValue>327635</FieldValue>
      </FieldValues>
      <FieldValues Field="Gender">
        <FieldValue>Male</FieldValue>
        <FieldValue>Female</FieldValue>
      </FieldValues>
      <FieldValues Field="code">
        <FieldValue>55905</FieldValue>
      </FieldValues>
     </StudyFields>
    <StudyFields Rank="3">
      <FieldValues Field="id">
        <FieldValue>555828</FieldValue>
      </FieldValues>
      <FieldValues Field="Gender">
        <FieldValue>Male</FieldValue>
      </FieldValues>
      <FieldValues Field="code">
        <FieldValue>55407-1139</FieldValue>
        <FieldValue>77030</FieldValue>
        <FieldValue>90901</FieldValue>
        <FieldValue>23144</FieldValue>
      </FieldValues>
    </StudyFields>
  </StudyFieldsList>
</StudyFieldsResponse>

我有上面的.xml文件。 為了提取idGendercode記錄,我對其進行了如下解析。

library(XML)
dat <- xmlParse(file = "example.xml")
final_dat <- xmlToDataFrame(nodes = xmlChildren(xmlRoot(dat)[["StudyFieldsList"]]))
names(final_dat) <- c("id", "Gender", "code")
> final_dat
      id     Gender                      code
1 327635 MaleFemale                     55905
2 555828       Male 55407-1139770309090123144

但是,請注意,對於第一行,有 2 個Gender ,男性和女性。 同理,對於第二個, code也不止1個。 如何擴展我的 data.frame 以便 data.frame 包含每個唯一idGendercode組合的唯一行?

> final_dat_expanded
          id     Gender            code
    1 327635       Male           55905
    2 327635     Female           55905
    3 555828       Male      55407-1139
    4 555828       Male           77030
    5 555828       Male           90901
    6 555828       Male           23144

對於復雜的嵌套 XML,請考慮XSLT ,這是一種專用語言,旨在轉換 XML 文件。 在 Unix (Mac/Linux) 上,R 可以通過對開源實用程序xsltproc進行system調用來運行 XSLT 1.0 腳本。 在 Windows、R 上可以運行參數化的 PowerShell 腳本。

具體來說,在 XSLT 下面針對 code 下的最低級別 FieldValue ,然后有條件地檢索祖先節點的 id 和 gender ,並使用for-each映射所有性別節點。

XSLT (另存為.xsl,一個特殊的.xml文件)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/StudyFieldsResponse">
     <xsl:copy>
       <xsl:apply-templates select="descendant::FieldValues[@Field='code']/FieldValue"/>
     </xsl:copy>
    </xsl:template>
    
    <xsl:template match="FieldValues[@Field='code']/FieldValue">
     <xsl:variable name="curr_code"><xsl:value-of select="text()"/></xsl:variable>
     <xsl:for-each select="ancestor::StudyFields/FieldValues[@Field='Gender']/FieldValue">
       <xsl:copy>
           <id><xsl:value-of select="ancestor::StudyFields/FieldValues[@Field='id']/FieldValue"/></id>
           <gender><xsl:copy-of select="text()"/></gender>
           <code><xsl:copy-of select="$curr_code"/></code>
       </xsl:copy>
     </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

在線演示

R

library(XML)

# TRANSFORM INPUT TO FLATTER OUTPUT AND SAVE TO DISK
system("xsltproc style.xsl input.xml -o output.xml")
doc <- xmlParse("output.xml")

# BIND TO DATA FRAME
field_values_df <- xmlToDataFrame(doc)
field_values_df
#       id gender       code
# 1 327635   Male      55905
# 2 327635 Female      55905
# 3 555828   Male 55407-1139
# 4 555828   Male      77030
# 5 555828   Male      90901
# 6 555828   Male      23144

如果您使用 Windows,請考慮 PowerShell 腳本

PowerShell (另存為.ps1)

param ($xml, $xsl, $output)

$xslt = New-Object System.Xml.Xsl.XslCompiledTransform
$xslt.Load($xsl)
$xslt.Transform($xml, $output)

R

library(XML)

# TRANSFORM INPUT TO FLATTER OUTPUT AND SAVE TO DISK
system("PowerShell -ExecutionPolicy bypass -File transform.ps1 input.xml style.xsl output.xml")
doc <- xmlParse("output.xml")

# BIND TO DATA FRAME
field_values_df <- xmlToDataFrame(doc)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM