使用Powershell从多个XML文件中的元素获取数据以输出到另一个单个XML文件 [英] Get data from elements within multiple XML files for output to another, single XML file using Powershell

查看:229
本文介绍了使用Powershell从多个XML文件中的元素获取数据以输出到另一个单个XML文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我要承认我是Powershell(和编码)菜鸟.我在一些脚本中迷失了方向,但是我什至没有对任何达到能力的要求.我希望一些更有经验的人可以让我走上正确的道路.

I'll begin by confessing that I'm a Powershell (and coding) noob. I've stumbled my way through a few scripts, but I make no claims to anything even approaching competence. I'm hopeful that some more experienced folks can set me on the right track.

我正在尝试从多个XML文件中提取特定的元素数据,这些数据将用于填充另一个XML文件.我从中提取数据的文件是发票,我想获取发票号和时间戳并将这些值放入清单中.清单结构如下

I'm trying to pull specific element-data from multiple XML files, which will be used to populate another XML file. The files from which I'm pulling the data are invoices, and I'd like to grab the invoice number and timestamp and drop those values into a manifest. The manifest structure is as follows

<?xml version="1.0" encoding="utf-8"?>
<Manifest>
    <Invoice>
        <InvoiceID></InvoiceID>
        <Timestamp></Timestamp>
    </Invoice>
</Manifest>

我要从中提取的XML位于清单将保存在其中的目录的子目录中.为了简单起见,发票中的元素名称与清单中的相应元素相同.清单的文件夹结构为"C:\Projects\Powershell\Manifest\Manifest.xml",发票的文件夹结构为"C:\Projects\Powershell\Manifest\Invoices\*.xml".

The XMLs from which I am pulling are in a sub-directory of the directory in which the manifest will be saved. For the sake of simplicity, the element names within the invoices are identical to the corresponding elements within the manifest. The folder structure for the manifest is "C:\Projects\Powershell\Manifest\Manifest.xml" and for the invoices it is "C:\Projects\Powershell\Manifest\Invoices\*.xml".

使用以下代码,我可以从子目录"\Invoices"中的元素"InvoiceID"和"Timestamp"的数据中,仅从的第一个中获取数据. .但是,该代码确实为每个发票文件创建了一个条目.它只是使用从第一个文件获取的值来填充每个元素. (因此,例如,如果我在"\Invoices"目录中有三个Invoice XML文件,则会得到以下结果:三个<Invoice>复杂元素的实例,每个实例都填充有在其中找到的InvoiceIDTimestamp first 文件.因此,它正在对文件进行计数并输出相应数量的元素,只是从第一个文件中获取任何数据.)

With the following code I am able to grab the data from the elements "InvoiceID" and "Timestamp" of only the first XML in the sub-directory "\Invoices". The code does, however, create one entry for each Invoice file; it just fills each element with the value taken from the first file. (So, for example, if I have three Invoice XML files in the "\Invoices" directory, I get results of: three instances of the <Invoice> complex element, each populated with the InvoiceID and Timestamp found in the first file. So it's counting the files and outputting a corresponding number of elements, it just isn't getting data from any but the first.)

这是代码:

$files = Get-ChildItem "C:\Projects\Powershell\Manifest\Invoices\*.xml"

$xmlData = @"
    <Invoice>
        <InvoiceId>$InvID</InvoiceId>
        <Timestamp>$Timestamp</Timestamp>
    </Invoice>
"@
$Manifest = "C:\Projects\Powershell\Manifest\Manifest.xml"

ForEach ($file in $files) {
    $xmldoc = [xml](Get-Content $file)
    $InvID = $xmldoc.Manifest.Invoice.InvoiceID
    $Timestamp = $xmldoc.Manifest.Invoice.Timestamp
    ForEach ($xml in $xmldoc)
{
    Add-Content $Manifest $xmlData
}}

弄清楚这部分内容后,就可以正确格式化输出文件的结束标记了.

I can deal with properly formatting the closing tag of the output file once I have this piece figured out.

我知道我的循环肯定不正确,但是在仔细阅读这一内容直到我的大脑受到伤害之后,我终于诉诸了这个问题.我想念/弄错什么明显的东西?

I know I must be looping incorrectly, but after reading up on this until my brain hurts, I've finally resorted to asking the question. What obvious thing am I missing/messing up?

推荐答案

字符串插值(扩展) "..."@"<newline>...<newline>"@字符串立即 发生,并且所引用的变量当时包含的值 被使用.
结果,在foreach循环的每次迭代中都会输出 same 字符串(其值是在循环之前确定的).

String interpolation (expansion) in "..." and @"<newline>...<newline>"@ strings happens instantly, with the values that the referenced variables contain at that time getting used.
As a result, the same string - whose value was determined before the loop - is output in each iteration of your foreach loop.

您的用例要求一种模板化方法,其中字符串插值是 deferred ,将按需 调用该 em> then-current 变量值,使用$ExecutionContext.InvokeCommand.ExpandString() :

Your use case calls for a templating approach, where string interpolation is deferred, to be invoked on demand with the then-current variable values, using $ExecutionContext.InvokeCommand.ExpandString():

# Define the *template* string as a *literal* - with *single* quotes.
$xmlData = @'
    <Invoice>
        <InvoiceId>$InvID</InvoiceId>
        <Timestamp>$Timestamp</Timestamp>
    </Invoice>
'@

 # ...
 # ForEach ($file in $files) { ...
   # Perform interpolation *on demand* with $ExecutionContext.InvokeCommand.ExpandString()
   Add-Content $Manifest -Value $ExecutionContext.InvokeCommand.ExpandString($xmlData)
 # }

注意:

  • 还可以通过使用{...}中的括弧(例如${InvID})明确地描述变量名称来嵌入变量引用,有时可能需要 来消除歧义.

  • Variable references can also be embedded by explicitly delineating the variable names via enclosure in {...}, e.g., ${InvID}, which may situationally be required for disambiguation.

为了嵌入表达式/命令输出,请使用$(),即

In order to embed expressions / command output, use $(), the subexpression operator, as demonstrated below.

为了嵌入 verbatim $实例,请将其转为`$.

In order to embed verbatim $ instances, escape them as `$.

一个简单的示例:

# Define a template string, *single-quoted*, with *literal contents*:
#  - '$InvID' is simply literally part of the string, not a variable reference (yet).
#  - Ditto for $((Get-Date).TimeOfDay)
$strTempl = 'Invoice ID $InvID extracted at $((Get-Date).TimeOfDay).'

# Echo the template string as-is - unexpanded - ...
$strTempl

# ... and expand it on demand
$InvID = 1
$ExecutionContext.InvokeCommand.ExpandString($strTempl)

# ... and again, after assigning a different value to $InvID
$InvID = 2
$ExecutionContext.InvokeCommand.ExpandString($strTempl)

上面的结果类似:

Invoice ID $InvID extracted at $((Get-Date).TimeOfDay).  # template literal
Invoice ID 1 extracted at 11:38:12.2719300.              # first on-demand expansion
Invoice ID 2 extracted at 11:38:12.2766010.              # second on-demand expnsion


通过 Expand-String cmdlet以更易发现的方式显示$ExecutionContext.InvokeCommand.ExpandString()方法此GitHub功能请求.


Surfacing the $ExecutionContext.InvokeCommand.ExpandString() method in a more discoverable way, via an Expand-String cmdlet, is the subject of this GitHub feature request.

这篇关于使用Powershell从多个XML文件中的元素获取数据以输出到另一个单个XML文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆