Используйте -t
и -m
, чтобы определить соответствие шаблона, а затем примените другое выражение XPath с помощью -v
.
$ 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
Это "короткая строка на оболочке", но она совершенно неразборчива. Поэтому я бы все же предпочел XSLT-решение kjhughes. Не жертвуйте понятным кодом в пользу краткости.
Вы можете написать таблицу стилей, которая принимает входной параметр из командной строки, чтобы вам не пришлось изменять код XSLT, если вы хотите получить имена атрибутов другого элемента.
Как предложил @npostavs, внутри xmlstarlet все равно используется XSLT. Вы можете проверить сгенерированный XSLT, заменив -T
на -C
:
$ 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="' '"/>
</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()>1]">
<xsl:value-of select="' '"/>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Есть много других вариантов для изучения, см. документацию xmlstarlet.
person
Mathias Müller
schedule
26.01.2015