我有一个具有以下内容的xml,我的问题是如何从资源标签提取用户名和密码值,这里我们需要使用Shell脚本排除注释的资源标签并从未注释的资源标签中获取值。我尝试过,但是它正在从最新标记中获取值。有人可以帮我如何删除注释标签和从xml中获取值。
<?xml version='1.0' encoding='utf-8'?>
<!-- The contents of this file will be loaded for each web application -->
<!--
<Resource name="jdbcSource" auth="Container"
type="javax.sql.DataSource"
username="demo"
password="test"
driverClassName="driverclassname"
url="driver@host"
maxActive="20"
maxIdle="10"
/>
-->
<Resource auth="Container"
driverClassName="driverclassname" maxActive="100" maxIdle="30" maxWait="10000"
name="jdbcSource" password="test" type="javax.sql.DataSource"
url="driver@host"
username="demo"/>
</Context>
答案 0 :(得分:2)
首先,我的答案假设您具有实际格式正确的源XML。您提供的示例代码不是XML,因为它没有开头的根元素,即<Context>
-但我还是假设存在一个。
Bash功能本身并不十分适合解析XML。
此Bash FAQ声明以下内容:
如果必须使用Shell脚本,则使用XML特定的命令行工具,例如undesired results(还有其他类似的工具)。请参阅下载信息XMLStarlet-如果尚未安装XML Starlet。
使用XML Starlet,您可以运行以下命令:
uname=$(xml sel -t -v "/Context/Resource/@username" path/to/file.xml)
pword=$(xml sel -t -v "/Context/Resource/@password" path/to/file.xml)
echo "$uname $pword" # --> demo test
说明
uname=$(...)
在这里,我们利用here将XML Startlet命令的输出分配给名为uname
(即用户名)的变量。
xml sel -t -v "/Context/Resource/@username"
此命令分解如下:
xml
-调用XML Starlet命令。sel
-选择数据或查询XML文档。-t
-模板选项。-v
-打印XPATH表达式的值。"/Context/Resource/@username"
-Command substitution表达式,用于选择username
标签/元素的Resource
属性的值。 path/to/file.xml
此部分应替换为.xml
文件的真实路径。
同样,我们利用类似的命令来获取password
属性的值,从而将命令的输出分配给名为pword
的变量,并更改XPATH表达式。
根据下面xpath的第一条评论...您还可以改用以下命令来更有效地提取两个属性值:
{ IFS= read -r uname && IFS= read -r pword; } < <(xml sel -t -v "/Context/Resource/@username" -n -v "/Context/Resource/@password" path/to/file.xml)
echo "$uname $pword" # --> demo test
这里的主要好处是源XML文件仅被读取一次。
xsltproc
的任何系统上运行,包括未安装XML Starlet的主机:根据Charles Duffy在下面的第二条评论...
还可以利用XML Starlet来生成Charles Duffy模板,该模板是从先前显示的XML Starlet查询派生的。然后,可以在具有xslt可用的任何系统上运行所生成的.xsl
文件(包括未安装XML Starlet的主机)。
以下步骤演示了如何实现此目的:
首先运行以下XML Starlet命令以生成.xsl
文件:
xml sel -C -t -v "/Context/Resource/@username" -n -v "/Context/Resource/@password" path/to/file.xml > path/to/resultant/my-template.xsl
此命令与先前显示的XML Starlet命令非常相似。显着的区别是:
-C
和sel
之间的附加-t
选项 xsltproc运算符>
和文件路径。这指定保存输出的位置(即生成的XSLT模板/样式表)。
注意,应根据需要更改path/to/resultant/my-template.xsl
部分。
生成的XSLT样式表的内容将类似于以下内容:
my-template.xsl
<?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:call-template name="value-of-template">
<xsl:with-param name="select" select="/Context/Resource/@username"/>
</xsl:call-template>
<xsl:value-of select="' '"/>
<xsl:call-template name="value-of-template">
<xsl:with-param name="select" select="/Context/Resource/@password"/>
</xsl:call-template>
</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>
接下来,运行以下命令,该命令利用redirection转换源.xml
文件。最终将转换结果分配给两个变量,即uname
和pword
:
{ IFS= read -r uname && IFS= read -r pword; } < <(xsltproc path/to/resultant/my-template.xsl path/to/file.xml)
echo "$uname $pword" # --> demo test
注意,应根据需要更改读取path/to/resultant/my-template.xsl
和path/to/file.xml
的部分。
答案 1 :(得分:1)
RobC already explained为什么不应该使用本机Bash工具来解析html / xml。我建议使用专用工具,例如xidel。
我添加了<Context>
,as shown by m.nguyencntt开头,并将xml文件另存为so_54034541.xml
。
使用命令替换,您当然可以通过两次调用xidel
来设置变量...
uname=$(xidel -s so_54034541.xml -e '//Resource/@username')
pword=$(xidel -s so_54034541.xml -e '//Resource/@password')
...但是xidel
也有自己的导出(多个)变量的方式:
xidel -s so_54034541.xml -e '//Resource/(uname:=@username,pword:=@password)'
uname := demo # Internal variables for use within the extraction query itself.
pword := test
xidel -s so_54034541.xml -e '//Resource/(uname:=@username,pword:=@password)' --output-format=bash
uname='demo' # At the moment these are just strings.
pword='test' # Use Bash's eval built-in command to actually set/export these variables.
eval "$(xidel -s so_54034541.xml -e '//Resource/(uname:=@username,pword:=@password)' --output-format=bash)"
echo "$uname $pword"
demo test
答案 2 :(得分:0)
使用perl一根内衬纸
ui
答案 3 :(得分:0)
我这样做如下:
创建了yourxmlfile.xml
<Context>
<Resource auth="Container"
driverClassName="driverclassname" maxActive="100" maxIdle="30" maxWait="10000"
name="jdbcSource" password="test" type="javax.sql.DataSource"
url="driver@host"
username="demo"/>
</Context>
sed -n's /.[^] * password =“([[^”] )。 / \ 1 / p'yourxmlfile.xml
test