我有以下示例XML:
<?xml version="1.0" encoding="utf-8"?>
<SQLUsers>
<SQLFile>
<FileVersion>260</FileVersion>
<FileDate>06.14.2014</FileDate>
</SQLFile>
<SQLAccount>
<user001>
<AccountName>user001</AccountName>
<SQLSysAdmin>Adm_user001</SQLSysAdmin>
<SQLSysAdminPassword>P@ssw0rd</SQLSysAdminPassword>
<SQLReadOnlyUser>user004</SQLReadOnlyUser>
<SQLReadOnlyUserPassword>P@ssw0rd</SQLReadOnlyUserPassword>
<CreationDate>06.13.2014</CreationDate>
<InstanceID>InstanceID</InstanceID>
</user001>
</SQLAccount>
<SQLAccount>
<user002>
<AccountName>user002</AccountName>
<SQLSysAdmin>Adm_user001</SQLSysAdmin>
<SQLSysAdminPassword>P@ssw0rd</SQLSysAdminPassword>
<SQLReadOnlyUser>user005</SQLReadOnlyUser>
<SQLReadOnlyUserPassword>P@ssw0rd</SQLReadOnlyUserPassword>
<CreationDate>06.13.2014</CreationDate>
<InstanceID>InstanceID</InstanceID>
</user002>
</SQLAccount>
</SQLUsers>
我应该更新这个XML文件,在&#34; UserXXX&#34;下添加一个新元素。节点。像这样的东西:
<user002>
<AccountName>user002</AccountName>
<SQLSysAdmin>Adm_user001</SQLSysAdmin>
<SQLSysAdminPassword>P@ssw0rd</SQLSysAdminPassword>
<SQLReadOnlyUser>user005</SQLReadOnlyUser>
<SQLReadOnlyUserPassword>P@ssw0rd</SQLReadOnlyUserPassword>
<CreationDate>06.13.2014</CreationDate>
<InstanceID>InstanceID</InstanceID>
<DatabaseName>database1</DatabaseName>
<DatabaseName>database2</DatabaseName>
</user002>
我有以下powershell脚本,它接受用户名,数据库名称作为参数:
param($accountName,$database)
$ErrorActionPreference = "Stop"
[string]$date = Get-Date -format "MM.dd.yyyy"
$Instanceid = "Testid"
[xml] $xml = gc "C:\LogFiles\$Instanceid-SQLUsers.xml"
$child = $xml.CreateElement("DatabaseName")
$child.SetAttribute('DatabaseName','$database')
$xml.SQLUsers.SQLAccount.$accountName.AppendChild($child)
$xml.save("C:\LogFiles\$Instanceid-SQLUsers_update.xml")
但是,我收到以下错误:
You cannot call a method on a null-valued expression.
At D:\Scripts\AttachUserToDB_XML3.ps1:12 char:1
+ $xml.SQLUsers.SQLAccount.$accountName.AppendChild($child)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : InvokeMethodOnNull
我也尝试使用innerXML,但是,没有用。 任何帮助将不胜感激!
非常感谢!
答案 0 :(得分:0)
由于您的xml结构具有多个sqlaccount标记,因此您将无法导航到确切的用户帐户元素。
将xml结构更改为具有单个sqlaccounts并列出所有用户或使用xpath查询检索确切的用户元素并在其上调用appendChild。
答案 1 :(得分:0)
您的xml设计糟糕。节点应该有&#34;标准&#34;名称,以便您可以针对架构验证xml。你有一个user0002
- 节点,它有点无用,因为这个值已在AccountName
- 元素中指定。这样:
<SQLAccount>
<user002>
<AccountName>user002</AccountName>
</use002>
</SQLAccount>
应该简化为类似的东西(因为AccountName元素已经包含用户名/唯一值):
<SQLAccount>
<AccountName>user002</AccountName>
</SQLAccount>
但是要回答你的问题,我想指出一些事情:
问题在于,当您运行$xml.SQLUsers.SQLAccount.$accountName
时,会得到两个项目的数组:空对象和xmlelement,因此您需要指定$xml.SQLUsers.SQLAccount.$accountName[1]
来获取节点。如果帐户不存在,您仍然会得到两个项目的数组:两个空对象。所以请记住验证是否找到了该节点。防爆。检查AccountName
- 属性是否存在。
您也在创建错误的元素。您的示例不包含databasename
- 属性,但您的脚本会尝试创建一个。
您的脚本从一个文件读取并保存到另一个文件。因此,为了能够添加您样本中显示的多个数据库,您的脚本需要在一次调用中支持多个数据库名称。
你可以试试这个:
function UpdateXML {
param($accountName,[string[]]$database)
$Instanceid = "Testid"
[xml] $xml = gc "C:\LogFiles\$Instanceid-SQLUsers.xml"
#case sensitive! easy to read
#$accountnode = $xml.SelectSingleNode("//AccountName[. = '$accountName']").parentnode
#case insensitive
$accountnode = $xml.SQLUsers.SQLAccount.$accountName[1]
#If a node for the account was found
if($accountnode.AccountName) {
foreach ($dbname in $database) {
$element = $xml.CreateElement("DatabaseName")
$element.InnerText = $dbname
$accountnode.AppendChild($element) | Out-Null
}
$xml.save("C:\LogFiles\$Instanceid-SQLUsers_update.xml")
} else {
Write-Error "Account '$accountName' doesn't exist!"
}
}
UpdateXML -accountName "user002" -database "database1", "database2"