【问题标题】:retreive sample or a given amount of nodes with xmlstarlet使用 xmlstarlet 检索样本或给定数量的节点
【发布时间】:2022-11-08 04:25:39
【问题描述】:

我正在使用一个巨大的 xml 文件,我需要获取 500 个节点的样本,这些节点是根节点的直接子节点。我知道它们属于同一类型。我需要得到这 500 个节点的所有子节点。

xmlstarlet 有办法这样做吗?

我更喜欢使用这个特定的包,因为我已经在使用它来对同一文件进行其他操作。

我尝试查看包的帮助页面,但找不到方法

【问题讨论】:

  • @Cyrus > 我尝试查看包的帮助页面,但找不到方法

标签: xml parsing xmlstarlet


【解决方案1】:

你可以试试:

xmlstarlet sel -t -c "/root/child[position() <= 500]" file.xml
  • sel 是查询 XML 的标准方法
  • 使用sel 时始终需要-t
  • -c 用于C操作
    (无论您在 xpath 中接下来选择什么)
  • /root/child 是 xpath
    (显然替换为实际元素名称)
  • [position() &lt;= 500] 选择位置(在根元素内)为 500 或更小的所有节点。

有时,我发现将路径括在括号中可以使选择起作用:

xmlstarlet sel -t -c "(/root/child)[position() <= 500]" file.xml

但一般来说,第一种方法就足够了。


所以,给定一个输入:

<root>
    <child>...</child>
    <child>...</child>
    ...
</root>

你会得到:

<child>...</child><child>...</child>...

请注意,没有语法上有效的 XML。

要使用换行符分隔,请尝试以下变体:

xmlstarlet sel -t -m "/root/child[position() <= 500]" -c "." -n file.xml
  • -m刚刚连接 xpath
    (不产生输出)
  • -c "." 复制匹配的节点
  • -n 附加一个n每个匹配/复制节点后的换行符

第 2 部分 - 选择某种类型的前“n”个节点

假设您想从以下 XML('example.xml')中获取前 3 个苹果:

<root>
    <apple>Braeburn</apple>
    <banana>Chiquita</banana>
    <apple>Granny Smith</apple>
    <plantain/>
    <apple>Cox</apple>
    <apple>Elstar</apple>
    <apple/>
    <apple/>
</root>

然后你可以使用:

xmlstarlet sel -t -m "/root/apple[position() <= 3]" -c "." -n example.xml

这又与前面的例子基本相同。
通过添加元素名称 ('apple'),您将专门选择前三个苹果节点,如以下输出所示:

<apple>Braeburn</apple>
<apple>Granny Smith</apple>
<apple>Cox</apple>

注意&lt;banana&gt;Chiquita&lt;/banana&gt;&lt;plantain/&gt; 是如何被忽略的。
它们不是&lt;apple/&gt; 类型的直接&lt;root/&gt; 子代。

奖金:

假设您想获得第三个苹果,那么您可以使用:

xmlstarlet sel -t -c "/root/apple[position() = 3]" example.xml

这会给你:&lt;apple&gt;Cox&lt;/apple&gt;

甚至更短:

xmlstarlet sel -t -c "/root/apple[3]" example.xml

再次给你同样的结果。

【讨论】:

  • 感谢@RvT,第一个解决方案(没有括号)就像一个魅力。我想其他人可能有兴趣知道如何检索特定类型的第一个 x 元素。如果您知道该怎么做,您是否可以考虑将其添加到您的答案中?
  • 很高兴听到@fbee。对于您的后续问题,您能否详细说明一下?
  • 例如,类似: 仅从 &lt;things&gt;&lt;fruit&gt;&lt;apple/&gt;&lt;orange/&gt;&lt;/fruit&gt;&lt;brands&gt;&lt;apple/&gt;&lt;McDonalds/&gt;&lt;/brands&gt;&lt;/things&gt; 中选择 &lt;apple/&gt;
  • 这不是我的意思。我调整了你的例子并改写了这个问题。我的问题是从 <things> <fruit> <apple /> </fruit> <fruit> <orange /> </fruit> <brand> <apple /> < 中提取所有 &lt;fruit&gt; 节点及其所有子节点/brand> <brand> <麦当劳 /> </brand> </things> `
  • @fbee - 所以如果我理解正确:如果输入是&lt;things&gt;&lt;fruit&gt;...&lt;/fruit&gt;&lt;brands&gt;...&lt;/brands&gt;&lt;/things&gt;,你只想得到&lt;apple/&gt;&lt;orange/&gt;(即&lt;fruit&gt;...&lt;/fruit&gt; 中的前 x 项)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多