我目前正在尝试将一些XML文档提供给脚本并将其初始化为[PSCustomObject]
。 XML文档需要分成几个对象然后加在一起。
这是我的剧本:
[xml]$CourseStructureIn = Get-Content .\Sample.xml
$data = foreach ($Instances in $CourseStructureIn.Node.instances.courseInstance) {
$instancearray = foreach ($instance in $instances) {
$hash = [ordered]@{ CourseInstanceID = $instance.courseInstanceID}
[PSCustomObject]@{
CourseCode = $instance.CourseCode
InstanceCode = $instance.instanceCode
session = $instance.session
quota = $instance.quota
}
}
$hash.Add("Instances", $instancearray)
$modules = $instance.L1Modules.L1Module
$modulearray = foreach ($module in $modules) {
[PSCustomObject]@{
moduleCode = $module.moduleCode
moduleTypeCode = $module.moduleTypeCode
moduleInstanceID = $module.moduleInstanceID
semester = $module.semester
credits = $module.credits
overallGradeWeighting = $module.overallGradeWeighting
fees = $module.fees
documents = $module.documents
}
}
$hash.Add("Modules", $modulearray)
$roles = $instance.L1Modules.L1Module.roles.role
$rolearray = foreach ($role in $roles) {
[PSCustomObject]@{
rolesGUID = $role.GUID
rolesIDNumber = $role.idnumber
roleFirstName = $role.firstname
roleSurname = $role.surname
}
}
$hash.Add("Roles", $rolearray)
这正确地将XML结构导入到对象数组的2个不同实例中 - 我应该提到XML最初来自normailzed数据库,因此每个XML文档或多或少代表一个表 - 最终成为一个多维数组在PowerShell中。
$data.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array
我可以参考各个数组对象
$data[0].roles | ft rolesGUID rolesIDNumber roleFirstName roleSurname --------- ------------- ------------- ----------- 55001420 55001420 R M 55001414 55001414 S C 55001234 55001234 C H 55001342 55001342 O C 55001414 55001414 S C 55001342 55001342 O C 55001445 55001445 M M 55001422 55001422 A H 55001001 55001001 P M 55001079 55001079 V S 55000770 55000770 A M 55000906 55000906 M B
我希望能够ConverTo-Html
进行报告 - 但我不知道如何枚举这种类型的结构 - 我应该留下的是一个包含一对多关系的表(是多维数组或锯齿状数组?)有人能给我一些关于如何输出这些类型结构的指针吗?当输出是某种类型的矩阵时,迭代数组或对象是很好的 - 但是当结构是某些列的多行而其他列的单行时我们会使用什么。
例如我的输出Format-Table
:
$data | ft CourseInstanceID Instances Modules ---------------- --------- ------- PGDDA_353650876 @{CourseCode=PGDDA; InstanceCode=PGDSP; session=2014; quota=999; Instances=; CourseInstanceID=PGDDA_353650876; Modules=System.Object[]; Roles=System.Object[]} {@{moduleCode=H... PGDDA_418403503 @{CourseCode=PGDDA; InstanceCode=PGDSP; session=2015; quota=999; Instances=; CourseInstanceID=PGDDA_418403503; Modules=System.Object[]; Roles=System.Object[]} {@{moduleCode=H...
我已经尝试过扩展属性并且已经在网上阅读,所以任何指针都会非常感激。
以下是成员:
$data | gm TypeName: System.Management.Automation.PSCustomObject Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() CourseInstanceID NoteProperty string CourseInstanceID=PGDDA_353650876 Instances NoteProperty Selected.System.Management.Automation.PSCustomObject Instances=@{CourseCode=PGDDA; InstanceCode=PGDSP; session=2014; quota=999; Instances=; CourseInstanceID=PGDD... Modules NoteProperty Object[] Modules=System.Object[] Roles NoteProperty Object[] Roles=System.Object[]
谢谢 - 我不能在这里分享XML文档,但是我会从我的具体例子中脱离出一般的例子。
假设我们有许多以下XML文档
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<author>Tiny Tim</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>$44.95</price>
<price>€40.50</price>
<price>£35.99</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
<TableOfContents>
<chapter Title = "Introduction" Number = "1" Page = "1"></chapter>
<chapter Title = "XSD" Number = "2" Page = "14"></chapter>
<chapter Title = "XPATH" Number = "3" Page = "27"></chapter>
<chapter Title = "XQUERY" Number = "4" Page = "42"></chapter>
<chapter Title = "XHTML" Number = "5" Page = "58"></chapter>
<chapter Title = "XSLT" Number = "6" Page = "75"></chapter>
</TableOfContents>
</book>
</catalog>
我想将此转换为此格式的表格(图片抱歉)
我还应该提一下,文档中可能有很多书节点,所以我希望每本书都有一个表格。
答案 0 :(得分:0)
好的,所以已经过了一个星期,但我不在办公室。我想我有一个解决你问题的方法。我编写了一个函数,递归调用自身来展平XML数组。由于数组可能包含具有相同名称的列,因此我将它们展平为Array1.Column1,Array1.Column2的命名上下文。为了更好地参考,在您的示例中,chapter
数组将展平为列chapter.Title
,chapter.Number
和chapter.Page
。
所以,首先我加载你的示例XML:
[xml]$Data = @'
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<author>Tiny Tim</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>$44.95</price>
<price>€40.50</price>
<price>£35.99</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
<TableOfContents>
<chapter Title = "Introduction" Number = "1" Page = "1"></chapter>
<chapter Title = "XSD" Number = "2" Page = "14"></chapter>
<chapter Title = "XPATH" Number = "3" Page = "27"></chapter>
<chapter Title = "XQUERY" Number = "4" Page = "42"></chapter>
<chapter Title = "XHTML" Number = "5" Page = "58"></chapter>
<chapter Title = "XSLT" Number = "6" Page = "75"></chapter>
</TableOfContents>
</book>
</catalog>
'@
现在我有了这个,我创建了一个递归地展平任何数组的函数,并查看它找到的任何对象,看它们是否包含数组:
Function Flatten-SubNode([object]$NodeIn){
$Node = $NodeIn.Clone()
$XMLExcludes = $Node.psobject.Methods.name|where({$_ -like 'get_*'})|%{$_.Substring(4)}
[array]$NodeProps = $Node.psobject.properties.name|?{$_ -notin $XMLExcludes}
$FlattenedNode = New-Object PSObject
$FlattenedProps = @()
ForEach($Property in $NodeProps)
{
Switch($Node.$Property){
{$_ -is [string]} {If($Property -notin $FlattenedProps){Add-Member -InputObject $FlattenedNode -NotePropertyName $Property -NotePropertyValue @();$FlattenedProps += $Property};$FlattenedNode.$Property += $_; continue}
{$_ -is [array]} {
Switch($_){
{$_ -is [string]}{[array]$Strings += $_;continue}
{$_ -isnot [array]}{
$SubItem=$_
ForEach($SubProp in ($_.PSObject.Properties.Name|Where{$_ -notin $XMLExcludes})){
If("$Property.$SubProp" -notin $FlattenedProps){
Add-Member -InputObject $FlattenedNode -NotePropertyName "$Property.$SubProp" -NotePropertyValue @()
$FlattenedProps += "$Property.$SubProp"
}
$FlattenedNode."$Property.$SubProp" += $SubItem.$SubProp
}
Continue}
default {
Flatten-SubNode $_|%{
$SubItem=$_
ForEach($SubProp in ($_.PSObject.Properties.Name|Where{$_ -notin $XMLExcludes})){
If("$Property.$SubProp" -notin $FlattenedProps){
Add-Member -InputObject $FlattenedNode -NotePropertyName "$Property.$SubProp" -NotePropertyValue @()
$FlattenedProps += "$Property.$SubProp"
}
$FlattenedNode."$Property.$SubProp" += $SubItem.$SubProp
}
}
}
}
If($Strings){$Node.$Property = $Strings}Else{$Node = $Node | Select * -ExcludeProperty $Property}
}
default {
$SubItem=Flatten-SubNode $_
ForEach($SubProp in ($SubItem.PSObject.Properties.Name|Where{$_ -notin $XMLExcludes})){
If("$Property.$SubProp" -notin $FlattenedProps){
Add-Member -InputObject $FlattenedNode -NotePropertyName "$Property.$SubProp" -NotePropertyValue @()
$FlattenedProps += "$Property.$SubProp"
}
$FlattenedNode."$Property.$SubProp" += $SubItem.$SubProp
}
}
}
}
$FlattenedNode
}
这是一个单个对象,其属性是任何给定列的记录数组。然后计算任何给定列的记录数,并取最大数。然后,它从顶部开始创建许多对象,并将所有可能的列作为属性。第一个将始终具有每个属性的值。当它移动通过更多属性时,最终没有值,因为数组已耗尽。例如,只有第一个对象具有该书的ID值,因为该书只有1个ID,而前2个对象在Author列中有一个值,所有对象在章节中都有值。标题, chapter.Number和chapter.Page属性,因为该数组的记录最多。
ForEach($Book in $Data.catalog.book){
$FlattenedBook = Flatten-SubNode $Data.catalog.book
$Rows=$Flattenedbook.psobject.properties.name|%{$FlattenedBook.$_.count}|sort -Descending|Select -first 1
$Results=For($i=0;$i -le $Rows;$i++){
$RowObj = New-Object PSObject
$Flattenedbook.psobject.properties.name|%{
add-member -InputObject $RowObj -NotePropertyName $_ -NotePropertyValue $Flattenedbook.$_[$i]}
$RowObj
}
$Results | ConvertTo-Html -Property * -as Table -Fragment |Set-Content C:\Temp\$($Book.id).htm
}
我将其设置为根据我在C:\ temp文件夹中的书籍ID号输出文件。我认为它运行得相当好,因为它只输出一个名为C:\ temp \ bk101.htm的文件(运行代码片段以查看结果表):
<table>
<colgroup><col/><col/><col/><col/><col/><col/><col/><col/><col/><col/></colgroup>
<tr><th>id</th><th>author</th><th>title</th><th>genre</th><th>price</th><th>publish_date</th><th>description</th><th>TableOfContents.chapter.Title</th><th>TableOfContents.chapter.Number</th><th>TableOfContents.chapter.Page</th></tr>
<tr><td>bk101</td><td>Gambardella, Matthew</td><td>XML Developer's Guide</td><td>Computer</td><td>$44.95</td><td>2000-10-01</td><td>An in-depth look at creating applications with XML.</td><td>Introduction</td><td>1</td><td>1</td></tr>
<tr><td></td><td>Tiny Tim</td><td></td><td></td><td>Ç40.50</td><td></td><td></td><td>XSD</td><td>2</td><td>14</td></tr>
<tr><td></td><td></td><td></td><td></td><td>£35.99</td><td></td><td></td><td>XPATH</td><td>3</td><td>27</td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td>XQUERY</td><td>4</td><td>42</td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td>XHTML</td><td>5</td><td>58</td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td>XSLT</td><td>6</td><td>75</td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
</table>
&#13;