Xml 如果元数据相同,如何组合成单个属性?
我有这样的Msbuild XML文件Xml 如果元数据相同,如何组合成单个属性?,xml,powershell,msbuild,powershell-2.0,msbuild-4.0,Xml,Powershell,Msbuild,Powershell 2.0,Msbuild 4.0,我有这样的Msbuild XML文件 <?xml version="1.0" encoding="utf-8"?> <Project xmlns="schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Notifications Include="someone@gmail.com"/> </ItemGroup
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Notifications Include="someone@gmail.com"/>
</ItemGroup>
<ItemGroup>
<Xcopy Include="..\..\..\Release\UtilitiesAssembly.dll">
<Destination>"..\..\..\Mycomponent\depl\BOM\Folder1</Destination>
</Xcopy>
<Xcopy Include="..\..\..\Release\Core.assembly.dll">
<Destination>"..\..\..\Mycomponent\depl\BOM\Folder1</Destination>
</Xcopy>
<Xcopy Include="..\..\..\Release\UIAssembly.dll">
<Destination>"..\..\..\Anothercomponent\Folder1</Destination>
</Xcopy>
<Xcopy Include="..\..\..\Release\Core.assembly.dll">
<Destination>"..\..\..\Anothercomponent\depl\BOM</Destination>
</Xcopy>
</Itemgroup>
</Project>
“.\..\..\Mycomponent\depl\BOM\Folder1
“.\..\..\Mycomponent\depl\BOM\Folder1
“.\..\..\Anothercomponent\Folder1
“.\..\..\Anothercomponent\depl\BOM
实际上,我想像这样对XCopy Itemgroup进行分组
<Xcopy Include="..\..\..\Release\UtilitiesAssembly.dll;
..\..\..\Release\\Core.assembly.dll;">
<Destination>"..\..\..\Mycomponent\depl\BOM\Folder1</Destination>
</Xcopy>
<Xcopy Include="..\..\..\Release\UIAssembly.dll;">
<Destination>"..\..\..\Anothercomponent\Folder1</Destination>
</Xcopy>
<Xcopy Include="..\..\..\Release\Core.assembly.dll">
<Destination>"..\..\..\Anothercomponent\depl\BOM</Destination>
</Xcopy>
“.\..\..\Mycomponent\depl\BOM\Folder1
“.\..\..\Anothercomponent\Folder1
“.\..\..\Anothercomponent\depl\BOM
如何使用Powershell或Msbuild或通过其他机制实现此功能这里是一个使用
Group Object
cmdlet实现此功能的示例。它将按目的地
对xcopy元素进行分组,并将包含
路径组合成分号分隔的字符串。输出存储在一个新的XML文档中,并使用ved到磁盘。这不会以编程方式更新原始XML。您只需将新的合并XML复制粘贴到原始XML上即可
现在更新我看到了您的整个文件,我看到它有一个默认名称空间,这会导致XPath出现问题
$xml="Myinput.xml"
$tempXmlFile = "C:\New.xml"
$outXml = New-Object System.Xml.XmlDocument
$outXml.AppendChild($outXml.CreateElement("root")) > $null
$x = [xml] (Get-Content $xml)
$x.SelectNodes("//*[local-name()='Xcopy']") | Group-Object Destination | % {
$includePaths = ($_.Group | Select-Object -ExpandProperty Include) -join ";"
$element = $outXml.CreateElement("Xcopy")
$element2 = $outXml.CreateElement("Destination")
$element2.InnerText = $_.Name
$element.AppendChild($element2) > $null
$element.SetAttribute("Include", $includePaths)
$outXml.DocumentElement.AppendChild($element) > $null
}
$outXml.Save($tempXmlFile)
$data = Get-Content $tempXmlFile | % {
$search = 'Include="'
$index = $_.IndexOf('Include="')
if ($index -gt 0) {
$spaces = ( ' ' * ($index + $search.length) )
}
$_ -replace ';', ";`n${spaces}"
}
$data | Set-Content $tempXmlFile
& notepad $tempXmlFile
创建输出:
<root>
<Xcopy Include="..\..\..\Release\UtilitiesAssembly.dll
..\..\..\Release\Core.assembly.dll">
<Destination>"..\..\..\Mycomponent\depl\BOM\Folder1</Destination>
</Xcopy>
<Xcopy Include="..\..\..\Release\UIAssembly.dll">
<Destination>"..\..\..\Anothercomponent\Folder1</Destination>
</Xcopy>
<Xcopy Include="..\..\..\Release\Core.assembly.dll">
<Destination>"..\..\..\Anothercomponent\depl\BOM</Destination>
</Xcopy>
</root>
“.\..\..\Mycomponent\depl\BOM\Folder1
“.\..\..\Anothercomponent\Folder1
“.\..\..\Anothercomponent\depl\BOM
下面是一个如何使用组对象
cmdlet执行此操作的示例。它将根据Destination
对xcopy元素进行分组,并将Include
路径组合成分号分隔的字符串。输出存储在新的XML文档中并保存到磁盘。这不会以编程方式更新原始文件。您只需将新的合并XML复制粘贴到原始XML上即可
更新现在我看到了您的整个文件,我看到它有一个默认名称空间,这会导致XPath出现问题。有两种方法可以解决这个问题
$xml="Myinput.xml"
$tempXmlFile = "C:\New.xml"
$outXml = New-Object System.Xml.XmlDocument
$outXml.AppendChild($outXml.CreateElement("root")) > $null
$x = [xml] (Get-Content $xml)
$x.SelectNodes("//*[local-name()='Xcopy']") | Group-Object Destination | % {
$includePaths = ($_.Group | Select-Object -ExpandProperty Include) -join ";"
$element = $outXml.CreateElement("Xcopy")
$element2 = $outXml.CreateElement("Destination")
$element2.InnerText = $_.Name
$element.AppendChild($element2) > $null
$element.SetAttribute("Include", $includePaths)
$outXml.DocumentElement.AppendChild($element) > $null
}
$outXml.Save($tempXmlFile)
$data = Get-Content $tempXmlFile | % {
$search = 'Include="'
$index = $_.IndexOf('Include="')
if ($index -gt 0) {
$spaces = ( ' ' * ($index + $search.length) )
}
$_ -replace ';', ";`n${spaces}"
}
$data | Set-Content $tempXmlFile
& notepad $tempXmlFile
创建输出:
<root>
<Xcopy Include="..\..\..\Release\UtilitiesAssembly.dll
..\..\..\Release\Core.assembly.dll">
<Destination>"..\..\..\Mycomponent\depl\BOM\Folder1</Destination>
</Xcopy>
<Xcopy Include="..\..\..\Release\UIAssembly.dll">
<Destination>"..\..\..\Anothercomponent\Folder1</Destination>
</Xcopy>
<Xcopy Include="..\..\..\Release\Core.assembly.dll">
<Destination>"..\..\..\Anothercomponent\depl\BOM</Destination>
</Xcopy>
</root>
“.\..\..\Mycomponent\depl\BOM\Folder1
“.\..\..\Anothercomponent\Folder1
“.\..\..\Anothercomponent\depl\BOM
从MSBuild 3.5开始,您可以使用
“.\..\..\Mycomponent\depl\BOM\Folder1
“.\..\..\Anothercomponent\Folder1
从MSBuild 3.5开始,您可以使用
“.\..\..\Mycomponent\depl\BOM\Folder1
“.\..\..\Anothercomponent\Folder1
我收到以下问题。无法将值“E:\Powershellscripts\Comp1.Targets”转换为类型“System.Xml.XmlDocument”。错误:“根级别的数据无效。第1行,位置1。“我的输入文件如下所示”“..\..\..\Mycomponent\depl\BOM\Folder1”“。\..\..\Mycomponent\depl\BOM\Folder1如果将Get content$xml替换为$xml,我会遇到相同的错误。所以我编辑了答案。谢谢你,伙计。@Samselvaprabu Woops我把你的源XML放在一个here字符串中进行了一点不同的测试。我将我的更新复制到答案中,没有为您重新调整。谢谢。我收到了以下问题,伙计。无法将值“E:\Powershellscripts\Comp1.Targets”转换为类型“System.Xml.XmlDocument”。错误:“根级别的数据无效。第1行,位置1。”我的输入文件如下“…\…\Mycomponent\depl\BOM\Folder1”“..\..\..\Mycomponent\depl\BOM\Folder1如果将Get content$xml替换为$xml,则我会遇到与我遇到的相同的错误。所以我编辑了答案。谢谢你,伙计。@Samselvaprabu Woops我把你的源XML放在一个here字符串中进行了一点不同的测试。我将我的更新复制到答案中,没有为您重新调整。谢谢。我认为Itemdefinitiongroup如果能为所有人提供通用的元数据,就可以工作了。这是一个有用的信息。我进一步澄清了我的问题。它对这种情况有效吗?我认为Itemdefinitiongroup可以工作,如果它对所有人都有公共元数据的话。这是一个有用的信息。我进一步澄清了我的问题。这个案子行得通吗?