如何在 groovy 中使用 xmlstarlet?
How can I use xmlstarlet in groovy?
我有一个 bash 脚本,它使用 xmlstarlet 来处理一些 xml。 我需要将 bash 脚本移植到 Groovy(以使用 Jenkins 管道)并且我在 xml 处理部分 遇到问题。我知道可以使用 GPath,但我有兴趣尽可能使用 xmlstarlet。这是我的 bash 脚本的简化:
count=$(xmlstarlet sel -t -v "count(//Result/Dataset[@name='PackageMap_Dataset']/Row)" /tmp/DataPipeLineScript-output-step4.xml)
echo count
为了实现它,我尝试了这个 Groovy 但是脚本输出错误:
def count="xmlstarlet sel -t -v \"count(//Result/Dataset[@name='PackageMap_Dataset']\" DataPipeLineScript-output-step4.xml".execute().text
println "Number of detected DataSets: " + count
没有@name的简化版也有同样的问题:
def count="xmlstarlet sel -t -v 'count(//Result/Dataset' DataPipeLineScript-output-step4.xml".execute().text
println "Number of detected DataSets: " + count
即使这个简单的执行也会失败,没有输出:
println "xmlstarlet".execute().text
def count= "xmlstarlet".execute().text
println "Number of detected DataSets: " + count
我怎样才能让它工作?
此处供参考xml
<Result>
<Dataset name='PackageMap_Dataset'>
<queryname>getcoordmissinglocations</queryname>
<Row>
<superfilename>~foo::indexes::develop::LocationsToEnrich::Super</superfilename>
<indexfilename>~foo::indexes::develop::LocationsToEnrich_20160912_143427</indexfilename>
</Row>
<Row>
<queryname>getcoordmissingsoiltype</queryname>
<superfilename>~foo::indexes::develop::SoilTypesToEnrich::Super</superfilename>
<indexfilename>~foo::indexes::develop::SoilTypesToEnrich_20160912_143427</indexfilename>
</Row>
<Row>
<queryname>getngrmissinglatlong</queryname>
<superfilename>~foo::indexes::develop::LatLongsToEnrich::Super</superfilename>
<indexfilename>~foo::indexes::develop::LatLongsToEnrich_20160912_143427</indexfilename>
</Row>
</Dataset>
<Dataset name='Result 2'>
</Dataset>
<Dataset name='Result 3'>
</Dataset>
<Dataset name='Result 4'>
</Dataset>
</Result>
更新
我已更新代码以显示@cfrick
建议的错误
//def proc = "xmlstarlet sel -t -v 'count(//Result/Dataset)' DataPipeLineScript-output-step4.xml".execute();
def proc = ["xmlstarlet", "sel", "-t", "-v", "\"count(//Result/Dataset)\"","DataPipeLineScript-output-step4.xml"].execute()
def outputStream = new StringBuffer();
def errorStream = new StringBuffer();
proc.waitForProcessOutput(outputStream, errorStream);
println("OUTPUT: " + outputStream.toString());
println("ERROR: " + errorStream.toString());
Groovy 只是生成带有参数的新进程 - 而不是 shell。所以不需要引用params(其中shells需要单独留下params)。在这种情况下,对 xmlstarlet
查询的引用会让它思考,只需要返回一个常量字符串(请参阅问题中的 OUTPUT: count(//Result/Dataset)
)。
因此,只需使用 [].execute()
进行适当的参数分隔,不要引用 shell,不要使用 shell 功能(如管道、重定向等) :
["xmlstarlet", "sel", "-t", "-v", "count(//Result/Dataset)", "DataPipeLineScript-output-step4.xml"].execute()
如果需要"shellisms",请使用
["sh", "-c", "... | ... > 'quote weird files.txt' ..."].execute()
或者您的 shell 如何处理这种 "eval me that line" 情况。
我有一个 bash 脚本,它使用 xmlstarlet 来处理一些 xml。 我需要将 bash 脚本移植到 Groovy(以使用 Jenkins 管道)并且我在 xml 处理部分 遇到问题。我知道可以使用 GPath,但我有兴趣尽可能使用 xmlstarlet。这是我的 bash 脚本的简化:
count=$(xmlstarlet sel -t -v "count(//Result/Dataset[@name='PackageMap_Dataset']/Row)" /tmp/DataPipeLineScript-output-step4.xml)
echo count
为了实现它,我尝试了这个 Groovy 但是脚本输出错误:
def count="xmlstarlet sel -t -v \"count(//Result/Dataset[@name='PackageMap_Dataset']\" DataPipeLineScript-output-step4.xml".execute().text
println "Number of detected DataSets: " + count
没有@name的简化版也有同样的问题:
def count="xmlstarlet sel -t -v 'count(//Result/Dataset' DataPipeLineScript-output-step4.xml".execute().text
println "Number of detected DataSets: " + count
即使这个简单的执行也会失败,没有输出:
println "xmlstarlet".execute().text
def count= "xmlstarlet".execute().text
println "Number of detected DataSets: " + count
我怎样才能让它工作?
此处供参考xml
<Result>
<Dataset name='PackageMap_Dataset'>
<queryname>getcoordmissinglocations</queryname>
<Row>
<superfilename>~foo::indexes::develop::LocationsToEnrich::Super</superfilename>
<indexfilename>~foo::indexes::develop::LocationsToEnrich_20160912_143427</indexfilename>
</Row>
<Row>
<queryname>getcoordmissingsoiltype</queryname>
<superfilename>~foo::indexes::develop::SoilTypesToEnrich::Super</superfilename>
<indexfilename>~foo::indexes::develop::SoilTypesToEnrich_20160912_143427</indexfilename>
</Row>
<Row>
<queryname>getngrmissinglatlong</queryname>
<superfilename>~foo::indexes::develop::LatLongsToEnrich::Super</superfilename>
<indexfilename>~foo::indexes::develop::LatLongsToEnrich_20160912_143427</indexfilename>
</Row>
</Dataset>
<Dataset name='Result 2'>
</Dataset>
<Dataset name='Result 3'>
</Dataset>
<Dataset name='Result 4'>
</Dataset>
</Result>
更新 我已更新代码以显示@cfrick
建议的错误 //def proc = "xmlstarlet sel -t -v 'count(//Result/Dataset)' DataPipeLineScript-output-step4.xml".execute();
def proc = ["xmlstarlet", "sel", "-t", "-v", "\"count(//Result/Dataset)\"","DataPipeLineScript-output-step4.xml"].execute()
def outputStream = new StringBuffer();
def errorStream = new StringBuffer();
proc.waitForProcessOutput(outputStream, errorStream);
println("OUTPUT: " + outputStream.toString());
println("ERROR: " + errorStream.toString());
Groovy 只是生成带有参数的新进程 - 而不是 shell。所以不需要引用params(其中shells需要单独留下params)。在这种情况下,对 xmlstarlet
查询的引用会让它思考,只需要返回一个常量字符串(请参阅问题中的 OUTPUT: count(//Result/Dataset)
)。
因此,只需使用 [].execute()
进行适当的参数分隔,不要引用 shell,不要使用 shell 功能(如管道、重定向等) :
["xmlstarlet", "sel", "-t", "-v", "count(//Result/Dataset)", "DataPipeLineScript-output-step4.xml"].execute()
如果需要"shellisms",请使用
["sh", "-c", "... | ... > 'quote weird files.txt' ..."].execute()
或者您的 shell 如何处理这种 "eval me that line" 情况。