在 xmlstarlet 上使用 xpath 检索 XML 元素的所有属性名称



我可以看到如何检索所有属性值:
xml sel -t -v "//element/@*"

但我想获取所有属性名称
例如,我可以通过以下方式获取第 n 个名称,它返回第 3 个属性名称xml sel -t -v "name(//x:mem/@*[3])"
但是xml sel -t -v "name(//x:mem/@*)"不起作用(仅返回第一个属性名称)...

有没有办法获取所有属性名称?

使用 -t-m 定义模板匹配项,然后应用另一个带有 -v 的 XPath 表达式。

$ xml sel -T -t -m "//mem/@*" -v "name()" -n input.xml

应用于此输入 XML 时:

<root>
    <mem yes1="1" yes2="2"/>
    <other no="1" no2="2"/>
</root>

将打印:

yes1
yes2

这是"壳上的短线",但完全无法理解。因此,我仍然更喜欢 kjhughes 的 XSLT 解决方案。不要为了简洁而牺牲可理解的代码。

您可以编写一个从命令行获取输入参数的样式表,这样,如果要检索其他元素的属性名称,则不必更改 XSLT 代码。


正如@npostavs所建议的,在内部,xmlstarlet无论如何都会使用XSLT。您可以检查通过将-T替换为 -C 生成的 XSLT

$ xml sel -C -t -m "//mem/@*" -v "name()" -n app.xml
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
  <xsl:output omit-xml-declaration="yes" indent="no"/>
  <xsl:template match="/">
    <xsl:for-each select="//mem/@*">
      <xsl:call-template name="value-of-template">
        <xsl:with-param name="select" select="name()"/>
      </xsl:call-template>
      <xsl:value-of select="'&#10;'"/>
    </xsl:for-each>
  </xsl:template>
  <xsl:template name="value-of-template">
    <xsl:param name="select"/>
    <xsl:value-of select="$select"/>
    <xsl:for-each select="exslt:node-set($select)[position()&gt;1]">
      <xsl:value-of select="'&#10;'"/>
      <xsl:value-of select="."/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

还有更多选项可供探索,请参阅 xmlstarlet 文档。

这个 xmlstarlet 命令:

xml tr attnames.xsl in.xml

使用此名为 attnames.xsl 的 XSLT 转换:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:template match="@*">
    <xsl:value-of select="name(.)"/>
    <xsl:text>&#xa;</xsl:text>
  </xsl:template>
  <xsl:template match="*">
    <xsl:apply-templates select="@*"/>
    <xsl:apply-templates select="*"/>
  </xsl:template>
</xsl:stylesheet>

而这个XML文件,命名为.xml:

<root att1="one">
  <a att2="two"/>
  <b att3="three">
    <c att4="four"/>
  </b>
</root>

将生成在 .xml 中找到的所有属性的列表:

att1
att2
att3
att4

若要仅从 b 元素中选择所有属性,请按如下所示修改 XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:template match="@*">
    <xsl:value-of select="name(.)"/>
    <xsl:text>&#xa;</xsl:text>
  </xsl:template>
  <xsl:template match="b">
    <xsl:apply-templates select="@*"/>
    <xsl:apply-templates select="*"/>
  </xsl:template>
  <xsl:template match="text()"/>
</xsl:stylesheet>

相关内容

  • 没有找到相关文章

最新更新