繁体   English   中英

使用XML解析器从XML元素获取值并将其分配给变量

[英]Obtain value from XML element using XML parser and assign it to a variable

我有以下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“ stylesheet”“ 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”),并将其分配给变量。

您能帮我解决该问题的方法吗?

就个人而言,我将使用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"

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

#!/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 '^(/ >| -----)'

我设法通过直接处理源XML文件而不是使用xsltproc来实现它。 在我的shell脚本中,我创建了以下变量:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM