首页 > 解决方案 > Powershell HasChildNodes 是否适用于文本?

问题描述

在 Powershell 中使用 XML 对象时,如果元素只有文本数据而不是另一个元素,HasChildNodes 是否应该返回 true?有没有办法识别下面没有任何实际元素的元素?

鉴于下面的示例,我希望元素 Parameter_Section 会为有孩子返回 true,但我不希望里面的元素在有数据的情况下也返回 true。例如,SCM_Included、SendToApp 和 WF_Start 都返回 true,因为它们有文本。定义说“获取一个指示此节点是否有任何子节点的值”。这是否意味着文本或数据被视为子节点?

我正在解析一堆 InfoPath XML 文件,我希望能够忽略像 Parameter_Section 这样的父元素,它们仅用于组织(InfoPath 将它们称为“部分”)实际存储数据的子元素(它们是 InfoPath 中的字段)。

function ReadAllNodes ($node) {
foreach ($childnode in $node.ChildNodes)
{
    [string] $path = Get-XPath($childnode)
    [string] $nt = $childnode.NodeType
    [string] $hc = $childnode.HasChildNodes
    [string] $name = $childnode.Name
    [string] $val = $childnode.Value
    [string] $txt = $childnode.'#text'

    Write-Host (“Name={0}, path={1}, type={2}, hc={3}, val={4}, txt={5}” -f $name, $path, $nt, $hc,$val,$txt)
}

foreach ($cn in $childnode) {
    ReadAllNodes $cn
    }
}

$Xml = @"
<?xml version="1.0" encoding="utf-8"?>
<myFields>
    <Parameter_Section>
        <Approval_Mode />
        <SCM_Included>n</SCM_Included>
        <ApprovalCompleteDateTime />
        <ApprovalCompleteDateStr />
        <SendToApp>No</SendToApp>
        <WF_Start>0</WF_Start>
        <QuoteAttachCount>0</QuoteAttachCount>
        <TestEmail />
        <TestMessage />
        <IsCurrentUserRequestor>true</IsCurrentUserRequestor>
        <CanCurrentUserApprove>Approve</CanCurrentUserApprove>
    </Parameter_Section>
</myFields>
"@

$content = New-Object -TypeName XML
$content.LoadXml($Xml)
[System.Xml.XmlElement] $root = $content.get_DocumentElement()

ReadAllNodes $root





    Name=Parameter_Section, path=/myFields/Parameter_Section, type=Element, hc=True, val=, txt=
Name=Approval_Mode, path=/myFields/Parameter_Section/Approval_Mode, type=Element, hc=False, val=, txt=
Name=SCM_Included, path=/myFields/Parameter_Section/SCM_Included, type=Element, hc=True, val=, txt=n
Name=ApprovalCompleteDateTime, path=/myFields/Parameter_Section/ApprovalCompleteDateTime, type=Element, hc=False, val=, txt=
Name=ApprovalCompleteDateStr, path=/myFields/Parameter_Section/ApprovalCompleteDateStr, type=Element, hc=False, val=, txt=
Name=SendToApp, path=/myFields/Parameter_Section/SendToApp, type=Element, hc=True, val=, txt=No
Name=WF_Start, path=/myFields/Parameter_Section/WF_Start, type=Element, hc=True, val=, txt=0
Name=QuoteAttachCount, path=/myFields/Parameter_Section/QuoteAttachCount, type=Element, hc=True, val=, txt=0
Name=TestEmail, path=/myFields/Parameter_Section/TestEmail, type=Element, hc=False, val=, txt=
Name=TestMessage, path=/myFields/Parameter_Section/TestMessage, type=Element, hc=False, val=, txt=
Name=IsCurrentUserRequestor, path=/myFields/Parameter_Section/IsCurrentUserRequestor, type=Element, hc=True, val=, txt=true
Name=CanCurrentUserApprove, path=/myFields/Parameter_Section/CanCurrentUserApprove, type=Element, hc=True, val=, txt=Approve
Name=#text, path=/myFields/Parameter_Section/CanCurrentUserApprove/#text, type=Text, hc=False, val=Approve, txt=

标签: xmlpowershellxml-parsing

解决方案


这是否意味着文本或数据被视为子节点?

是的,确实如此。

节点内的字符串“Approve”<CanCurrentUserApprove>本身就是一个XmlText节点。如您所料,您可以通过该ChildNodes属性访问文本节点。

试试下面的例子:

$content.SelectNodes('//CanCurrentUserApprove')[0].ChildNodes[0]

推荐阅读