使用shell工具(如grep,awk或sed)解析xml

问题描述:

我有以下xml解析并根据标记的值提取标记的值。仅当type =='hosted'时才提取。我想使用像grep,sed和awk这样的bash工具进行提取。在没有条件的情况下提取单个标签值是我之前完成的,而不是条件。我可以很容易地使用Python或我知道的任何其他编程语言来完成它。但是如果在shell脚本中完成,这将是理想的。使用shell工具(如grep,awk或sed)解析xml

... 
    <repositories-item> 
     <name>hosted-npm</name> 
     <type>hosted</type> 
    </repositories-item> 
    <repositories-item> 
     <name>proxied-npm</name> 
     <type>proxied</type> 
    </repositories-item> 
... 
+1

我强烈建议您使用XML工具来处理XML(在Python等中)。特别是,您可以考虑编写一个合适的XSLT样式表,并使用脚本中的'xsltproc'命令将样式表应用于XML输入。 –

+0

查看[xmlstarlet](http://xmlstar.sourceforge.net/) –

缺乏XML专用工具

awk使用封闭的标签来定义记录抢救定界符

$ awk -v RS='</?repositories-item>' '/<type>hosted<\/type>/' file 

    <name>hosted-npm</name> 
    <type>hosted</type> 

注意,这需要多焦RS这GNU awk支持。

可以对匹配更多的控制和输出

$ awk -v RS='</?repositories-item>' -F'[<>]' ' 
    {delete a; 
    for(i=2;i<=NF;i+=4) a[$i]=$(i+1); 
    if(a["type"]=="hosted") print a["name"] }' file 


hosted-npm 

xmlstarlet是一个命令行工具包的XML可以表达复杂的XSLT模板作为命令行开关的短序列。

假设我们正在提供一个良好的XML文档repos.xml

<repositories> 
    <repositories-item> 
     <name>hosted-npm</name> 
     <type>hosted</type> 
    </repositories-item> 
    <repositories-item> 
     <name>proxied-npm</name> 
     <type>proxied</type> 
    </repositories-item> 
</repositories> 

如果通过XMLStarlet过滤器使用以下开关

$ cat repos.xml | xmlstarlet sel -t -m '//repositories-item' \ 
       -i 'type="hosted"' -v 'name' -n 

运行它,你会得到输出

的一行 ​​

让我们看看XMLStarlet命令li东北。

  1. 我们经营与sel开关指定的选择模式的命令
  2. 我们指定与-t开关
  3. 我们限制选择模板解析器与该-m swicth
  4. 指定的 //repositories-item模板 <repositories-item>元素
  5. 我们只选择这些元素作为type元素的“托管”值-i开关
  6. 我们打印出name元素的值,使用-v开关指定。
  7. 在每行输出之后,我们打印一个由-n开关指定的换行符。

这里是通过XMLStarlet

产生的等效XSLT
<?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="//repositories-item"> 
     <xsl:choose> 
     <xsl:when test="type=&quot;hosted&quot;"> 
      <xsl:call-template name="value-of-template"> 
      <xsl:with-param name="select" select="name"/> 
      </xsl:call-template> 
      <xsl:value-of select="'&#10;'"/> 
     </xsl:when> 
     </xsl:choose> 
    </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> 

每查尔斯达菲建议它值得注意的是,此XSLT规范可以使用XMLStarlet的-C选项生成:

xmlstarlet sel -C -t -m '//repositories-item' \ 
     -i 'type="hosted"' -v 'name' -n > hosted-repos.xslt 

这个生成的XSLT规范可以直接使用xsltproc作为

cat repos.xml | xsltproc hosted-repos.xslt - 
+2

可能值得向OP展示如何使用'xsltproc'来应用该XSLT,以确保他们明白他们可以在服务器上使用此解决方案没有安装XMLStarlet。 –