XML 数据扁平化,如何找回原始数据

XML Data flatten, how to get the original data back

我有一个包含以下示例数据的 txt 文件:

id,001
v1,some_value
id,002
v1,some_value
v2,some_value
id,003
v2,some_value
id,004
v4,some_value

原始数据具有xml结构。它被压平了。所以值的顺序很重要。

实际上,变量的数量很大(超过 1000 个)。并且存在嵌套结构:v1 可以是 v2 的父类别。我们在另一个文件中有此信息。

我的问题是:给定这个展平结构,我们怎样才能用 R 或 python 取回原始 xml 数据?

其实最后我想把这些值转换成结构化的表格数据,列有:id,v1,v2,v3等。所以如果先搞定这种格式比较简单,也是可以的。然后我们不需要嵌套结构变量来进行转换,而只需要按顺序排列的可能变量列表。假设对于上面的示例,我们有变量:v1、v2、v3 和 v4。所以最终数据将是:

[更新]:变量的顺序对于恢复原始数据很重要。

例如,如果我们有:

id,001
v1,some_value
id,002
v2,some_value
v1,some_value
id,003
v2,some_value
id,004
v4,some_value

那么,我们会得到:

您提到您在另一个文件中有现有字段。前提是您可以使用这些来制作一个命名的空白字符向量,如下所示:

existing_list <- c(id = "", v1 = "", v2 = "", v3 = "", v4 = "")

那么你可以这样做:

df <- read.csv(text = "my_textfile.csv", header = FALSE)

id_list <- split(df, cumsum(df$V1 == "id"))

do.call(rbind, lapply(id_list, function(x) {
  vec <- setNames(x$V2, x$V1)
  existing_list[match(names(vec), names(existing_list))] <- vec
  as.data.frame(as.list(existing_list))
  }))

#>    id         v1         v2 v3         v4
#> 1 001 some_value                         
#> 2 002 some_value some_value              
#> 3 003            some_value              
#> 4 004                          some_value

同样,这里没有使用外部包。

这是一种方法 Python。

假设输入文件'flattened_xml.txt'包含:

id,001
v1,some_value1
id,002
v2,some_value2
v1,some_value3
id,003
v2,some_value4
id,004
v4,some_value5

代码:

# Get lines of text file.
with open('flattened_xml.txt') as file:
    data = file.read().splitlines()

# Determine what fiels are present.
fields = []
for line in data:
    id, _ = line.split(',')
    if id not in fields:
        fields.append(id)

table = [{field:field for field in fields}]  # Header row.
row = {}
for line in data:
    field, value = line.split(',')

    if field == fields[0]:
        row = {field: value}
        row.update({key: None for key in fields[1:]})
        continue

    row.update({key: value if key == field else None for key in fields[1:]})
    table.append(row)
    row = {key: None for key in fields}

for row in table:
    s = [f'{value if value is not None else "":11}' for value in row.values()]
    print('|' + '|'.join(s) + '|')

结果:

|id         |v1         |v2         |v4         |
|001        |some_value1|           |           |
|002        |           |some_value2|           |
|           |some_value3|           |           |
|003        |           |some_value4|           |
|004        |           |           |some_value5|