xmlstarlet 通过属性而不是元素匹配/解析

Posted

技术标签:

【中文标题】xmlstarlet 通过属性而不是元素匹配/解析【英文标题】:xmlstarlet match/parsing by attribute instead of element 【发布时间】:2021-12-28 02:54:43 【问题描述】:

我有一个复杂的结构化 XML 文件,我尝试使用 xmlstartlet 从中解析一些值。我认为问题在于逻辑对象是由元素属性而不是实际元素名称来标识的。

为这个例子简化的文件 test.xml 看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<configDump>
  <cluster top-level-assembly="XYZ12312312312">
  </cluster>
  <views>
    <view status="ok" name="ABC">
      <viewInitiators>
        <viewInitiator id="ABCi1"></viewInitiator>
        <viewInitiator id="ABCi2"></viewInitiator>
      </viewInitiators>
      <viewPorts>
        <viewPort id="ABCp1"></viewPort>
        <viewPort id="ABCp2"></viewPort>
      </viewPorts>
      <viewVolumes>
        <viewVolume lun="1" id="ABCv1"></viewVolume>
        <viewVolume lun="2" id="ABCv2"></viewVolume>
      </viewVolumes>
    </view>
    <view status="ok" name="DEF">
      <viewInitiators>
        <viewInitiator id="DEFi1"></viewInitiator>
        <viewInitiator id="DEFi2"></viewInitiator>
      </viewInitiators>
      <viewPorts>
        <viewPort id="DEFp1"></viewPort>
        <viewPort id="DEFp2"></viewPort>
      </viewPorts>
      <viewVolumes>
        <viewVolume lun="1" id="DEFv1"></viewVolume>
        <viewVolume lun="2" id="DEFv2"></viewVolume>
      </viewVolumes>
    </view>
  </views>
</configDump>

我正在尝试使用如下所示的字段生成输出:

<top-level-assembly>-<view-name>,<viewInitiator-ID>

当我运行以下命令时:

xmlstarlet sel -t \
                -m //cluster \
                        --var sn=@top-level-assembly \
                -m //views/view \
                        --var view=@name \
                -m //views/view/viewInitiators/viewInitiator \
                        -v 'concat($sn,"-",$view,",",@id)' -n test.xml

我得到以下输出:

XYZ12312312312-ABC,ABCi1
XYZ12312312312-ABC,ABCi2
XYZ12312312312-ABC,DEFi1
XYZ12312312312-ABC,DEFi2
XYZ12312312312-DEF,ABCi1
XYZ12312312312-DEF,ABCi2
XYZ12312312312-DEF,DEFi1
XYZ12312312312-DEF,DEFi2

如您所见,我在每个“视图”下获取了所有“启动器”值,而不仅仅是 XML 中该结构中的值。我期待并希望得到:

XYZ12312312312-ABC,ABCi1
XYZ12312312312-ABC,ABCi2
XYZ12312312312-DEF,DEFi1
XYZ12312312312-DEF,DEFi2

对我做错了什么有什么想法吗?

【问题讨论】:

【参考方案1】:

对我做错了什么有什么想法吗?

-m 选项嵌套 - 到 xsl:for-each 语句 - 所以你要求每个 view 的所有 viewInitiator/@ids。要查看生成的 XSLT 代码,请在 -t 之前添加一个 -C 选项。

可以通过以下方式生成所需的输出:

xmlstarlet sel -t \
    --var sn='configDump/cluster/@top-level-assembly' \
    -m '//viewInitiator' \
       -v 'concat($sn,"-",../../@name,",",@id)' -n \
< file.xml

【讨论】:

谢谢!它实际上是最后一行中的“../../@name”,但我明白了要点!我是一个 XML 新手,xmlstarlet 文档不是很好(我认为它假设你有一些知识,但如果你不知道,我不会告诉你从哪里得到它),所以我很感激帮助。跨度> @Noso Opforu:您不是第一个对xmlstarlet 文档感到头疼的人。感谢您对丢失的../ 的提醒;现在已经修好了。

以上是关于xmlstarlet 通过属性而不是元素匹配/解析的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 xmlstarlet 为 xml 文件的每个节点添加不同的属性

使用 xmlstarlet 或 xmllint 获取属性值

info.plist - xmlstarlet 不返回指定节点

如何在解析之前检查 XML 中是不是存在属性和标签?

带有属性而不是元素的 Json 到 XML

.fadeOut() 方法使用可见性属性而不是显示属性