2017-01-25 29 views
0

我有下面的XML:使用XML解析器获取从XML元素的值,并将其分配给一个变量

 <?xml version="1.0" encoding="UTF-8"?> 
    <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" 
      xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
     <modelVersion>4.0.0</modelVersion> 
     <groupId>BundleResourceDeploy</groupId> 
     <artifactId>Project3</artifactId> 
     <version>1.0-SNAPSHOT</version> 
     <packaging>sbar</packaging> 
     <description></description> 
</project> 

另外我有以下XSLT样式表:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://maven.apache.org/POM/4.0.0" exclude-result-prefixes="ns"> 

<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/> 
<xsl:template match="ns:project"> 


    <xsl:element name="ns:groupId"> 
    <xsl:value-of select="ns:groupId"/> 
    </xsl:element> 

    <xsl:element name="ns:artifactId"> 
    <xsl:value-of select="ns:artifactId"/> 
    </xsl:element> 

    <xsl:element name="ns:version"> 
    <xsl:value-of select="ns:version"/> 
    </xsl:element> 

    <xsl:element name="ns:packaging"> 
    <xsl:value-of select="ns:packaging"/> 
    </xsl:element> 

</xsl:template> 
</xsl:stylesheet> 

执行命令:xsltproc的“样式表”, “XML_FILE”>的Output.xml

输出(的Output.xml文件的内容)为:

<ns:groupId xmlns:ns="http://maven.apache.org/POM/4.0.0">BundleResourceDeploy</ns:groupId><ns:artifactId xmlns:ns="http://maven.apache.org/POM/4.0.0">Project2</ns:artifactId><ns:version xmlns:ns="http://maven.apache.org/POM/4.0.0">1.0-SNAPSHOT</ns:version><ns:packaging xmlns:ns="http://maven.apache.org/POM/4.0.0">sbar</ns:packaging> 

我想实现的是: 在一个shell脚本中,我想要获取元素“groupId”的值,该值为“BundleResourceDeploy”,并将其分配给一个变量。

你能帮我解决这个问题吗?

回答

0

就个人而言,我会使用XMLStarlet:

#!/bin/bash 
#  ^^^^-- NOT /bin/sh; process substitution is an extension in ksh and bash 
#    $'' literal syntax is an extension as well, likewise read -d 

IFS=$'\n' read -r -d '' groupId artifactId version packaging < <(
    xmlstarlet sel \ 
    -N ns='http://maven.apache.org/POM/4.0.0' \ 
    -t -m /ns:project \ 
    -v ns:groupId -n \ 
    -v ns:artifactId -n \ 
    -v ns:version -n \ 
    -v ns:packaging -n \ 
    <pom.xml && printf '\0' 
) 

echo "pom.xml is for $groupId/$artifactId, version $version, with packaging $packaging" 

然而,是什么在脚本实际执行xmlstarlet命令完全等同于一个稍微不同的XSLT模板,你可以问XMLStarlet通过为您生成经过-C说法:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://maven.apache.org/POM/4.0.0" 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="/ns:project"> 
     <xsl:call-template name="value-of-template"> 
     <xsl:with-param name="select" select="ns:groupId"/> 
     </xsl:call-template> 
     <xsl:value-of select="'&#10;'"/> 
     <xsl:call-template name="value-of-template"> 
     <xsl:with-param name="select" select="ns:artifactId"/> 
     </xsl:call-template> 
     <xsl:value-of select="'&#10;'"/> 
     <xsl:call-template name="value-of-template"> 
     <xsl:with-param name="select" select="ns:version"/> 
     </xsl:call-template> 
     <xsl:value-of select="'&#10;'"/> 
     <xsl:call-template name="value-of-template"> 
     <xsl:with-param name="select" select="ns:packaging"/> 
     </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> 

请注意,我们不是在这里创造了我们的输出元件的全部,而是生成由换行符分隔文本流。 (如果换行符可能出现在我们的值中,我们需要调整我们的方法,但在Maven POM中不是这种情况)。


如果您使用我上面给的样式,确切的脚本是:

#!/bin/bash 
IFS=$'\n' read -r -d '' groupId artifactId version packaging \ 
    < <(xsltproc stylesheet.xslt pom.xml) && printf '\0') 

echo "pom.xml is for $groupId/$artifactId, version $version, with packaging $packaging" 
+0

的xmlsh工具是另一种可能性看 –

-2

我设法直接在源XML文件的工作,而不是与xsltproc的努力去实现它。在我的shell脚本中,我创建了以下变量:

GROUPID = “$(grep的-Po '?(< =)\ w +(=)' name_of_xml_file_here”

+1

不这样做,它可能在一个XML文件的工作,但它会失败在下一次。 ,因为你没有考虑到在格式良好的XML中可以合法发生的所有变化,你正在储存未来的问题。 –

+0

寻找更好的选择我设法解决它使用xmllint。我将在另一个答案中发布它 – Alfonso

0

下面使用xmllint一个更好的选择的例子是返回<version/>元素的值shell脚本:

#!/bin/bash 
echo 'setns ns=http://maven.apache.org/POM/4.0.0 
cat /ns:project/ns:version/text()' | \ 
xmllint --shell pom.xml | egrep -v '^(/ >| -----)' 
+0

您有使用'--shell'而不是'--xpath'的原因吗? '--shell'非常适合交互式使用,因此可以执行不像脚本那样的操作,例如将提示输出到stdout(并将提示字符串与提取的输出混合在一起)。 –

+0

...使用以编程方式交互使用的工具是有风险的,因为交互功能通常不是很好定义 - 仅仅因为当前版本中的提示符是'''并不意味着它会保留在未来,例如,所以你不能保证这个代码将继续工作。相比之下,XSLT处理器的输出完全*定义明确,并且不会违背标准而以任何相关的方式进行更改。 –

+0

...因此,使用xmllint执行此操作的更安全方法是:'xmllint --xpath'/*[namespace-uri()="http://maven.apache.org/POM/4.0.0“和本地名称()=“项目”]/* [namespace-uri()=“http://maven.apache.org/POM/4.0.0”和local-name()=“version”]/text )' –

相关问题