解析具有已知结构和重复元素的 XML 文件

2024-03-24

我正在尝试从包含大量具有重复名称的元素的 XML 文件中解析信息。

以下是我尝试解析的文件类型的示例,仅包含一条记录:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <!--
        Start of the FIRST record.
    -->
    <dict>
        <key>80211D_IE</key>
        <dict>
            <key>IE_KEY_80211D_CHAN_INFO_ARRAY</key>
            <array>
                <dict>
                    <key>IE_KEY_80211D_FIRST_CHANNEL</key>
                    <integer>1</integer>
                    <key>IE_KEY_80211D_MAX_POWER</key>
                    <integer>27</integer>
                    <key>IE_KEY_80211D_NUM_CHANNELS</key>
                    <integer>11</integer>
                </dict>
            </array>
            <key>IE_KEY_80211D_COUNTRY_CODE</key>
            <string>US</string>
        </dict>
        <key>AGE</key>
        <integer>0</integer>
        <key>AP_MODE</key>
        <integer>2</integer>
        <key>BEACON_INT</key>
        <integer>100</integer>
        <key>BSSID</key>
        <string>ac:5d:10:73:c3:11</string>
        <key>CAPABILITIES</key>
        <integer>1073</integer>
        <key>CHANNEL</key>
        <integer>2</integer>
        <key>CHANNEL_FLAGS</key>
        <integer>10</integer>
        <key>IE</key>
        <data>
        AAZPbGl2ZXIBCIKEiwwSlhgkAwECBwZVUyABCxswGAEAAA+sAgIAAA+sBAAP
        rAIBAAAPrAIAAN0aAFDyAQEAAFDyAgIAAFDyBABQ8gIBAABQ8gIqAQAyBDBI
        YGw=
        </data>
        <key>NOISE</key>
        <integer>0</integer>
        <key>RATES</key>
        <array>
            <integer>1</integer>
            <integer>2</integer>
            <integer>5</integer>
            <integer>6</integer>
            <integer>9</integer>
            <integer>11</integer>
            <integer>12</integer>
            <integer>18</integer>
            <integer>24</integer>
            <integer>36</integer>
            <integer>48</integer>
            <integer>54</integer>
        </array>
        <key>RSN_IE</key>
        <dict>
            <key>IE_KEY_RSN_AUTHSELS</key>
            <array>
                <integer>2</integer>
            </array>
            <key>IE_KEY_RSN_MCIPHER</key>
            <integer>2</integer>
            <key>IE_KEY_RSN_UCIPHERS</key>
            <array>
                <integer>4</integer>
                <integer>2</integer>
            </array>
            <key>IE_KEY_RSN_VERSION</key>
            <integer>1</integer>
        </dict>
        <key>RSSI</key>
        <integer>-74</integer>
        <key>SSID</key>
        <data>
        T2xpdmVy
        </data>
        <key>SSID_STR</key>
        <string>Oliver</string>
        <key>WPA_IE</key>
        <dict>
            <key>IE_KEY_WPA_AUTHSELS</key>
            <array>
                <integer>2</integer>
            </array>
            <key>IE_KEY_WPA_MCIPHER</key>
            <integer>2</integer>
            <key>IE_KEY_WPA_UCIPHERS</key>
            <array>
                <integer>4</integer>
                <integer>2</integer>
            </array>
            <key>IE_KEY_WPA_VERSION</key>
            <integer>1</integer>
        </dict>
    </dict>
    <!--
        End of the FIRST record.
        In reality, more records follow.
    -->
</array>
</plist>

我遇到的问题是,我想从本质上展平每个观察结果(上例中只有一个观察结果),以便第一个中的每个元素<array>(即每个<dict> within <array>) 是数据框中的一行,其中的每个元素<dict>是一列,由适当的名称命名<key>.

我已经尝试过以下功能XML包,主要是xmlToList,但还没有完全弄清楚解析 XML 数据的正确方法。


Edit:

我想要的输出或多或少是将每个记录展平为数据框或列表中的一行,以便可以通过键轻松访问值。我不一定关心保留任何层次结构,例如每条记录都会有<key>80211D_IE</key>随后是一个dict包含实际信息——<key>80211D_IE</key>不是必需的,因为它不包含任何真实信息,而只是一组项目的不必要的分组。我可以将其存储为列表,例如mydata$record1$X80211D_IE$I.E._KEY_80211D_CHAN_INFO_ARRAY$IE_KEY_80211D_FIRST_CHANNEL,或者在像这样的数据框中mydata[1, 'I.E._KEY_80211D_FIRST_CHANNEL'].

我现在遇到的最大问题是这个 XML 结构似乎不太适合解析。例如,如果我想将 XML 子集化为记录,其中SSID_STR匹配一个字符串,我不能只使用xmlToList因为它不知道键应该与其值相关联。所以我得到一个这样的列表:

> str(xmlToList("path/to/my/file.xml"), max.level=2)
List of 2
 $ array :List of 25
  ..$ dict:List of 36
  ..$ dict:List of 32
  ..$ dict:List of 32
  ..$ dict:List of 38
  ..$ dict:List of 36
  ..$ dict:List of 34
  ..$ dict:List of 34
  ..$ dict:List of 34
  ..$ dict:List of 34
  ..$ dict:List of 34
  ..$ dict:List of 32
  ..$ dict:List of 38
  ..$ dict:List of 38
  ..$ dict:List of 34
  ..$ dict:List of 36
  ..$ dict:List of 34
  ..$ dict:List of 36
  ..$ dict:List of 34
  ..$ dict:List of 36
  ..$ dict:List of 36
  ..$ dict:List of 40
  ..$ dict:List of 42
  ..$ dict:List of 36
  ..$ dict:List of 38
  ..$ dict:List of 38
 $ .attrs: Named chr "1.0"
  ..- attr(*, "names")= chr "version"

看看其中的一个

> str(xmlToList("path/to/my/file.xml")$array[[1]], max.level = 1)
List of 36
 $ key    : chr "80211D_IE"
 $ dict   :List of 4
 $ key    : chr "AGE"
 $ integer: chr "0"
 $ key    : chr "AP_MODE"
 $ integer: chr "2"
 $ key    : chr "BEACON_INT"
 $ integer: chr "100"
 $ key    : chr "BSSID"
 $ string : chr "a:18:a:31:0:83"
 $ key    : chr "CAPABILITIES"
 $ integer: chr "4145"
 $ key    : chr "CHANNEL"
 $ integer: chr "11"
 $ key    : chr "CHANNEL_FLAGS"
 $ integer: chr "10"
 $ key    : chr "HT_CAPS_IE"
 $ dict   :List of 12
 $ key    : chr "HT_IE"
 $ dict   :List of 34
 $ key    : chr "IE"
 $ data   : chr "\n\t\tAAR0ZXN0AQiWlgwSGCQwSAMBCwcGVVMgAQseKgEDMBgBAAAPrAICAAAPrAQA\n\t\tD6wCAQAAD6wCAAAyAmBsRgVzwAEAADMCDAstGowRG///AAAAAAAAAAA"| __truncated__
 $ key    : chr "NOISE"
 $ integer: chr "0"
 $ key    : chr "RATES"
 $ array  :List of 9
 $ key    : chr "RSN_IE"
 $ dict   :List of 8
 $ key    : chr "RSSI"
 $ integer: chr "-86"
 $ key    : chr "SSID"
 $ data   : chr "\n\t\tdGVzdA==\n\t\t"
 $ key    : chr "SSID_STR"
 $ string : chr "test"
 $ key    : chr "WPA_IE"
 $ dict   :List of 8

很容易看出,实际上只有 18 个项目,但密钥作为自己的项目存储(总共 36 个)。

The xmlToList函数实际上是almost我希望它做什么——而是使用相应键的值来命名包含数据的列表的元素。

这看起来像:

List of 18
 $ AGE          : chr "0"
 $ AP_MODE      : chr "2"
 $ BEACON_INT   : chr "100"
 $ BSSID        : chr "a:18:a:31:0:83"
 $ CAPABILITIES : chr "4145"
 $ CHANNEL      : chr "11"
 $ CHANNEL_FLAGS: chr "10"
 $ HT_CAPS_IE   :List of 12
 $ HT_IE        :List of 34
 $ IE           : chr "\n\t\tAAR0ZXN0AQiWlgwSGCQwSAMBCwcGVVMgAQseKgEDMBgBAAAPrAICAAAPrAQA\n\t\tD6wCAQAAD6wCAAAyAmBsRgVzwAEAADMCDAstGowRG///AAAAAAAAAAA"| __truncated__
 $ NOISE        : chr "0"
 $ RATES        :List of 9
 $ RSN_IE       :List of 8
 $ RSSI         : chr "-86"
 $ SSID         : chr "\n\t\tdGVzdA==\n\t\t"
 $ SSID_STR     : chr "test"
 $ WPA_IE       :List of 8
 $ X80211D_IE   :List of 4

在这个假设的输出中,使用适当的键很容易获取值。此外,继续取消嵌套列表(因为不需要分组结构)以生成数据框将很容易。


我将OP的XML存储在一个文件中但重复了所提供的单个记录!

使用一些附加的附加包这可能会更灵活(我会使用dplyr%>%),但我忍住了。我建议使用xml2代替XML。您可以使用 XPATH 表达式来定位感兴趣的节点。

x <- read_xml("so.xml")
(elements <- xml_find_all(x, ".//dict/dict/array/dict"))
#> {xml_nodeset (2)}
#> [1] <dict>\n                    <key>IE_KEY_80211D_FIRST_CHANNEL</key>\n ...
#> [2] <dict>\n                    <key>IE_KEY_80211D_FIRST_CHANNEL</key>\n ...

## isolate the key nodes ... will become variable names
keys <- lapply(elements, xml_find_all, "key")
keys <- lapply(keys, xml_text)
## I advise checking that keys are uniform across the records here!
(keys <- keys[[1]])
#> [1] "IE_KEY_80211D_FIRST_CHANNEL" "IE_KEY_80211D_MAX_POWER"    
#> [3] "IE_KEY_80211D_NUM_CHANNELS"

## isolate integer data
integers <- lapply(y, xml_find_all, "integer")
integers <- lapply(integers, xml_text)
integers <- lapply(integers, type.convert)
yay <- as.data.frame(do.call(rbind, integers))
names(yay) <- keys
yay
#>   IE_KEY_80211D_FIRST_CHANNEL IE_KEY_80211D_MAX_POWER
#> 1                           1                      27
#> 2                           1                      27
#>   IE_KEY_80211D_NUM_CHANNELS
#> 1                         11
#> 2                         11
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解析具有已知结构和重复元素的 XML 文件 的相关文章

  • 将逗号类分配给数据框中的多个列

    我有一个data frame有几个数字列我要 就像分配 逗号 类一样 这是需要的 因为我有一个中央数据框 我使用 Openxlsx 包过滤并保存到 Excel 并且需要comma类 以便数据在excel中显示为逗号格式 这是数据框 set
  • 使用 R 将我的 shapefile 数据投影到传单地图上

    我 在 Win7 上 试图获取我的 shapefile 数据 Here https www dropbox com s f3d46itleoozzjz shapefiles zip dl 0是数据文件 要使用显示leaflet包裹 但没有任
  • 以给定的纵横比保存绘图

    我正在使用非常棒的库 ggplot2 我想出了如何使用设置绘图的纵横比coord fixed 现在 我想将绘图保存为具有指定宽度 例如 10 厘米 的 PDF 并计算所需的高度 我不知道如何实现这一目标 这可能吗 您可以使用网格函数来计算
  • 最好的 php DOM 2 数组函数是什么?

    我想解析xml文件 到目前为止 我发现最好的方法是使用 DOMDocument 类 示例 xml 字符串
  • R:如何应用输出多列数据帧的函数(使用 dplyr)?

    我想查找数据框中某一特定列与所有其他列之间的相关性 p 值和 95 CI broom 包提供了一个示例 说明如何使用带有 dplyr 和管道的 cor test 在两列之间执行此操作 对于 mtcars 和 mpg 列 我们可以与另一列进行
  • 将数字提高到非整数幂时出现奇怪的 NaN [重复]

    这个问题在这里已经有答案了 我执行了以下代码 tau lt 0 25 h lt 0 6 n 1 5 4 5 dnorm qnorm tau 4 qnorm tau 2 qnorm tau 2 1 2 1 5 R 继续生产NaN 然而 R 实
  • EOutOfMemory 使用 Delphi 创建大型 XML

    我正在使用 Delphi 从关系数据库中的数据创建 XML 文档 它在小数据集上测试得很好 但是当我尝试将数据集的大小扩展到生产级别时 它最终在节点创建期间因 EOutOfMemory 异常而崩溃 我正在使用放在表单上的 TXMLDocum
  • dplyr / left_join 中的嵌套管链

    在尝试获取分组滞后变量的过程中 仅使用这是不可能的 lag 建议的解决方案是将数据拉出 滞后不同的行 然后重新加入它 我更喜欢在不创建中间对象的情况下执行此操作 并且希望在链中间执行此操作 然而 它似乎没有像我预期的那样工作 问题似乎是使用
  • 查找嵌套列表中元素的索引?

    我有一个类似的列表 mylist lt list a 1 b list A 1 B 2 c list C 1 D 3 是否有一种 无循环 方法来识别元素的位置 例如如果我想用 5 替换 C 的值 并且在哪里找到元素 C 并不重要 我可以这样
  • 在 R 中进行 Cox 回归后,将预测危险比列添加到数据帧中

    在 R 中运行 Cox PH 回归后 我需要在数据框中添加预测风险比的列 数据框是面板数据 其中 numgvkey 如果公司标识符 和年龄是时间标识符 您可以从此链接下载一小部分日期 https drive google com file
  • 指定 R 中 hist() 中的 bin 数量?

    我尝试指定垃圾箱的数量hist R为10 如下 gt hist x breaks 10 但垃圾箱的数量并不完全是 10 我尝试了几个其他数量的垃圾箱 结果发生了同样的情况 hist says breaks可以指定 给出直方图单元格数量的单个
  • 用于清除工作空间和转储存储的 R 全局函数

    我希望创建一个全局函数来清除我的工作区并转储我的内存 我将我的函数称为 cleaner 并希望它执行以下代码 remove list ls gc 我尝试在全局环境中创建该函数 但是当我运行它时 控制台仅打印该函数的文本 在我要获取的函数文件
  • 在 mac (iMac OSX ) 终端中远程运行脚本(r 脚本)到其他计算机

    我有一个小示例脚本 script p r 如下所示 打算在终端中运行 usr bin Rscript sink output capture txt mn lt mean 1 10 and so on much longer list of
  • 将 JSON URL 转换为 R 数据帧

    我在将 JSON 文件 从 API 转换为 R 中的数据帧时遇到问题 例如 URL 我尝试了 S O 的一些不同建议 包括将json数据转换为R中的数据框 https stackoverflow com questions 28683769
  • 如何在不循环的情况下添加组ID?

    我有数据框 例如 productid ordernum p1 10 p2 20 p3 30 p4 5 p5 20 p6 8 我想添加另一列 称为 groupid 它将产品按顺序分组在一起 一旦 sum ordernum 达到 30 分配一个
  • 将列表中的列转换为 R 中的数据框

    我有使用 R 创建的以下列表 set seed 326581 X1 rnorm 10 0 1 Y1 rnorm 10 0 2 data data frame X1 Y1 lst lt replicate 100 df smpl lt dat
  • 限制数据框中所有单元格的字符串长度?

    您好 有没有一种方法可以限制 data frame 中所有列的字符串文本大小 而不必循环遍历每一列并一次使用 str trunc 之类的东西 例如下面的数据框 我可以将所有文本大小限制为仅 5 个字符 而不必一次只执行一列吗 如果有 50
  • 从 R 环境中删除对象

    我正在阅读 Hadley 的 Advanced R 在第 8 章中 他说我们可以使用以下方法从环境中删除对象 rm 但是 移除该物体后我仍然可以看到该物体 这是我的代码 e lt new env e a lt 1 e b lt 2 e a
  • R.matlab/readMat:readTag(this) 中出错

    我正在尝试使用 R matlab 将 matlab 文件读入 R 但遇到此错误 require R matlab r lt readMat file mat verbose T Trying to read MAT v5 file stre
  • 在另一个 Rmd 中运行选定的块

    我已经在源 Rmd 文件中运行了分析 并且希望仅使用few来自源的块 我已经看到了一些关于从源 Rmd 中提取所有块的答案来自另一个 Rmd 中的 Rmd 文件的源代码 https stackoverflow com questions 4

随机推荐