所以我一直在研究一个存储有文件夹结构的XML文件,我希望能够验证文件系统中是否存在文件夹结构。虽然有很多种方法可以尝试这样做,但是......#Resolve-Path" "获取-ChildItems"等...我希望能够构建XML结构中的路径并将其放入字符串或其他内容中,我可以针对它运行Test-Path。听起来很容易吧?很可能对于一些经验丰富的Powershell老兵而言,这可能是我对PS的新手,并且在我的脑袋周围有一些困难。
以下是具有目录结构的XML示例
<config>
<local>
<setup>
<folder name="FolderA" type="root">
<folder name="FolderC"/>
<folder name="FolderB">
<folder name="FolderD" type="thisone"/>
</folder>
</folder>
</setup>
</local>
</config>
如果子节点设置为FolderD,最终目标是构建一个类似于此类的字符串
FolderA\FolderB\FolderD
对我而言,似乎很明显,为了获得完整的路径,你必须从最后开始并向后走节点树,然后我迷路了。 目的是仅从可能存在的多个路径中选择一个路径。所以我想检查FolderD的路径。因此,我必须构建该路径\ FolderA \ FolderB \ FolderD并忽略其余路径。
答案 0 :(得分:3)
最简单的方法可能是:
name
属性值构建路径,直到type=root
节点被点击$xmlDoc = [xml] @'
<config>
<local>
<setup>
<folder name="FolderA" type="root">
<folder name="FolderC"/>
<folder name="FolderB">
<folder name="FolderD" type="thisone"/>
</folder>
</folder>
</setup>
</local>
</config>
'@
# Get the leaf element of interest.
$leafNode = $xmlDoc.SelectSingleNode('//folder[@type="thisone"]')
# Simply build up the path by walking up the node hierarchy
# until an element with attribute type="root" is found.
$path = $leafNode.name
$node = $leafNode
while ($node.type -ne 'root') {
$node = $node.ParentNode
$path = $node.name + '\' + $path #'# (ignore this - fixes syntax highglighting)
}
# Output the resulting path:
# FolderA\FolderB\FolderD
$path
原始回答,基于问题的原始形式:对于从元素属性自上而下构建路径,使用递归,可能仍然感兴趣。< / p>
通过递归,您仍然可以采用自上而下的方法:
$xmlDoc = [xml] @'
<folder name="FolderA">
<folder name="FolderC"/>
<folder name="FolderB">
<folder name="FolderD"/>
</folder>
</folder>
'@
# Define a function that walks the specified XML element's hierarchy to
# down its leaf elements, building up a path of the values of the
# specified attribute, and outputting the path for each leaf element.
function get-LeafAttribPaths($xmlEl, $attrName, $parentPath) {
$path = if ($parentPath) { join-path $parentPath $xmlEl.$attrName } else
{ $xmlEl.$attrName }
if ($xmlEl.ChildNodes.Count) { # interior element -> recurse over children
foreach ($childXmlEl in $xmlEl.ChildNodes) {
get-LeafAttribPaths $childXmlEl $attrName $path
}
} else { # leaf element -> output the built-up path
$path
}
}
# Invoke the function with the document element of the XML document
# at hand and the name of the attribute from whose values to build the path.
$paths = get-LeafAttribPaths $xmlDoc.DocumentElement 'name'
# Output the resulting paths.
# With the above sample input:
# FolderA\FolderC
# FolderA\FolderB\FolderD
$paths
# Test paths for existence.
Test-Path $paths
答案 1 :(得分:2)
我会这样写:
drop shadow
在我的系统中它产生:
$xmlDoc = [xml]'<folder name="FolderA">
<folder name="FolderC"/>
<folder name="FolderB">
<folder name="FolderD"/>
</folder>
</folder>'
function Get-XmlPath($node, $pathPrefix){
$children = $node.SelectNodes('folder[@name]')
$path = [System.IO.Path]::Combine($pathPrefix, $node.name)
if ($children.Count) {
foreach($child in $children) {
Get-XmlPath $child $path
}
} else {
$path
}
}
Get-XmlPath $xmlDoc.DocumentElement | % { [PSCustomObject]@{Path = $_; Exist = Test-Path $_ } }
更新以反映新的xml结构
您可以按如下方式将搜索范围缩小到所选节点:
Path Exist
---- -----
FolderA\FolderC False
FolderA\FolderB\FolderD False
关键是从正确的节点开始。如果不合适,您也可以尝试其他选择器:
Get-XmlPath $xmlDoc.SelectSingleNode('//folder[@type="root"]') | % { [PSCustomObject]@{Path = $_; Exist = Test-Path $_ } }
答案 2 :(得分:1)
给出一个起始(子)元素并从那里开始钻进,这对我来说很好:
function Get-XPath (
[object]$Element
) {
if ($Element.ParentNode -eq $Null) {
return "/"
}
else {
return (Get-XPath $Element.ParentNode) + "/" + $Element.Name
}
}