使用bash脚本从XML节点提取字符串

时间:2018-09-10 20:24:23

标签: xml bash

我似乎找不到确切的方法。我有这个XML文件

<session>
  <translations>
   <translation>
      <inside>198.18.133.1</inside>
      <name>adfs.domain1.com</name>
    </translation>
    <translation>
      <inside>198.18.135.60</inside>
      <name>hds.domain2.com</name>
    </translation>
   </translations>
 </session>

,我想根据内部节点中找到的字符串从特定名称节点中提取域。如您所见,我在节点内部有多个名称。通过以下bash文件,我可以提取name的第一个实例

#!/bin/bash
domain="$(echo "cat /session/translations/translation/name/text()" | xmllint --nocdata --shell session.xml | sed '1d;$d')"
domain="${domain:5}"
printf '%s\n' "Domain is: $domain"

这将给我domain1.com。

有时候,我翻译的数量可能更少或更少,而且翻译的顺序不一定总是相同。所以我需要一种方法,如果内部节点匹配198.18.133.1,则拉出名称,或者如果内部节点匹配198.18.135.60,则拉出名称,等等。

希望如此。

谢谢

1 个答案:

答案 0 :(得分:1)

您当前的XPath表达式,为:

/session/translations/translation/name/text()

...可以轻松更改为:

/session/translations/translation[inside="198.18.133.1"]/name/text()

...执行所需的过滤。


使用XMLStarlet(而不是XMLLint)执行此操作可能看起来更像:

xmlstarlet sel -t -m '/session/translations/translation[inside="198.18.133.1"]/name' -v . -n

如果将-C参数添加到sel子命令中,它将发出XSLT模板,供其在后台进行评估,您可以在安装了xsltproc的任何位置运行它,包括没有XMLStarlet的系统:

<?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="/session/translation/translation[inside=&quot;198.18.133.1&quot;]/name">
      <xsl:call-template name="value-of-template">
        <xsl:with-param name="select" select="."/>
      </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>