Powershell insert XML here-string into xml document - powershell

I'm trying to insert an XML here-string into a XMLdocument. However, the saved XMLdoc, shows: "System.Xml.XmlDocument", not the content. How can I fix this?
[xml] $Doc = New-Object System.Xml.XmlDocument
$updateNode = [xml] "<Update>
<Request>Test</Request>
</Update>"
#Create XML declaration
$declaration = $Doc.CreateXmlDeclaration("1.0","UTF-8",$null)
#Append XML declaration
$Doc.AppendChild($declaration)
#Create root element
$root = $Doc.CreateNode("element","BrowseDetailsRequest",$null)
#Create node based on Here-String
$node = $Doc.CreateElement("element",$updateNode,$null)
#Append node
$root.AppendChild($node)
#Append root element
$Doc.AppendChild($root)
Output at this moment:
<?xml version="1.0" encoding="UTF-8"?>
<BrowseDetailsRequest>
<System.Xml.XmlDocument />
</BrowseDetailsRequest>

You don't really manipulate the text in the xml. Use the objects to manipulate the xml. So you need to create an element for update and request and then assign the innertext value of request.
$Doc = New-Object System.Xml.XmlDocument
$declaration = $Doc.CreateXmlDeclaration("1.0","UTF-8",$null)
$Doc.AppendChild($declaration)
$root = $Doc.CreateNode("element","BrowseDetailsRequest",$null)
$elUpdate = $doc.CreateElement("element","Update",$null)
$elRequest = $doc.CreateElement("element","Request",$null)
$elRequest.InnerText = "Test"
$elUpdate.AppendChild($elRequest)
$root.AppendChild($elUpdate)
$doc.AppendChild($root)

Related

Fill a variable in a condition from xml

what I have is a variable called $usercity.city obtained with a Msoluser query to get a user city.
What I need to do is to populate a variable called $icthead depending from that value. I mean I have like 30 cities with differents icthead, is there a way different from a simple switch to do that?
Like loading from an external XML or stuff like that... thanks! If you think a simple switch won't slow down my script I'm gonna go that way.
A pratic example of what I want to do is:
$usercity=Milan then $icthead=email1#company.it
$usercity=London then $icthead=email2#company.it
$usercity=chicago then $icthead=email3#company.it
but for 20 or more cities. A solution would be loading every email on an array[$usercity] but I can't do it by myself cause I'm really bad. Thanks in advance.
I'm not sure if something like this is what you are looking for, but if you have the data in an excel sheet with the e-mail for each city in a row of data, then you can grab the e-mail of that city this way:
foreach($city in $usercity.city)
{
icthead
function icthead {
# This part is to open up the designated xlsx file and make powershell "look" in it.
$Excel = New-Object -ComObject excel.application
$DestinationPath = "Your xlsx file location"
$workbook = $Excel.workbooks.open($DestinationPath)
$Sheet = $workbook.worksheets.item("Name of the excel tab your information is in")
$Sheet.activate()
# This will find the horizontal row that the city is in.
$GetCity = $Sheet.Range("Vertical range .ex B2:B9999").find("$City")
$Row = $GetCity.Row
# This will require you to download the ImportExcel module - https://www.powershellgallery.com/packages/ImportExcel/3.0.0 - All credit to Douglas Finke
$XL = Import-Excel "Your xlsx file location"
# .Mail is an example. Should be your column title. It will grab the value that is in that row under that column and save it in the variable. Remember that xlsx is 0 indexed.
$CityMail = $XL[$row].Mail
}
$IctHead = $CityMail
Write-host $IctHead
}
I think you are looking for an external reference. It can be done by many ways. Here is some of those:
Hashtable/Dictionary variable:
#declare hashtable type variable.
$ht = #{}
#populate it with key/value items.
$ht.Add('Milan','email1#company.it')
$ht.Add('London','email2#company.it')
$ht.Add('Chicago','email3#company.it')
#input city name Milan
$city = 'Milan'
#now call hashtable variable by its key Milan
$ht[$city]
#output
email1#company.it
#usage example
Set-UserProperty -City $city -Email $ht[$city]
XML string:
[xml]$xml = #"
<?xml version="1.0" encoding="utf-8" ?>
<Dictionary>
<City name="Milan">
<Email>email1#company.it</Email>
</City>
<City name="London">
<Email>email2#company.it</Email>
</City>
<City name="Chicago">
<Email>email3#company.it</Email>
</City>
</Dictionary>
"#
$xml.Dictionary.City | Where-Object {$_.name -eq $city} | Select -ExpandProperty Email
CSV string:
$city = 'Milan'
$CSV = #"
"City","Email"
"Milan","email1#company.it"
"London","email2#company.it"
"Chicago","email3#company.it"
"# | ConvertFrom-Csv
($CSV | Where-Object {$_.City -eq $city}).Email
#output
email1#company.it
XML/CSV files:
Create either a XML or a CSV file with the same content as those of the respective here string (#" ... "#). E.g:
myfile.xml:
<?xml version="1.0" encoding="utf-8" ?>
<Dictionary>
<City name="Milan">
<Email>email1#company.it</Email>
</City>
<City name="London">
<Email>email2#company.it</Email>
</City>
<City name="Chicago">
<Email>email3#company.it</Email>
</City>
</Dictionary>
myfile.csv:
"City","Email"
"Milan","email1#company.it"
"London","email2#company.it"
"Chicago","email3#company.it"
Replace the here string (#" ... "#) in the code above with Get-Content -Raw -Path 'myfile.xml' or Get-Content -Raw -Path 'myfile.csv', respectively. E.g:
[xml]$xml = Get-Content -Raw -Path 'myfile.xml'
or
$CSV = Get-Content -Raw -Path 'myfile.csv'
The rest of the code stays the same.

Using variables inside PowerShell replace

I'm trying to add some new settings to a tomcat server.xml file datasource. I can match the last setting in the datasource, which has a password that I need to capture, but when I try to replace it, I'm not see any changes.
$serverXml = "C:\server.xml"
$xml = Get-Content $serverXml
$password = (($xml -match " password=""(.*)""").Replace(' password="', "").Replace('" />', ''))[0]
$oldString = #"
username="cf.user"
password="$password" />
"#
$newString = #"
username="cf.user"
password="$password"
testWhileIdle="true"
testOnBorrow="true"
testOnReturn="false"
validationQuery="select 1"
validationInterval="30000"
minEvictableIdleTimeMillis="30000" />
"#
$xml = $xml.replace($oldString, $newString)
Set-Content -Path $serverXml -Value $xml
I'm able to match the $password fine, but when I'm using it as a variable to pass into $oldString and $newString in the replace, its not matching anymore. Even $xml -match $oldString doesn't return anything, but totally should as far as I can tell.
Do not edit XML via string replacements. Use the gratuitous XML parser PowerShell provides you with.
Load the config file like this:
[xml]$xml = Get-Content $serverXml
or like this:
$xml = New-Object Xml.XmlDocument
$xml.Load($serverXml)
The latter is a bit more failsafe, because it will (for instance) check that the encoding of the file actually matches the encoding specified in the preamble.
Select nodes via XPath expressions:
$node = $xml.SelectSingleNode('/Path/To/Node')
Change existing attributes like this:
$node.Attributes['password'] = 'newpassword'
Add new attributes like this:
$attr = $xml.CreateAttribute('testWhileIdle')
$attr.Value = 'true'
[void]$node.Attributes.Append($attr)
Then save the modified XML back to the file:
$xml.Save($serverXml)

Upload file to SharePoint Online with metadata using PowerShell

I'm trying to upload a batch of files to SharePoint Online using PowerShell and include metadata too (column fields). I know how to upload files, this works fine:
$fs = New-Object IO.FileStream($File.FullName,[System.IO.FileMode]::Open)
$fci= New-Object Microsoft.SharePoint.Client.FileCreationInformation
$fci.Overwrite = $true
$fci.ContentStream = $fs
$fci.URL = $file
$upload = $list.RootFolder.Files.Add($fci)
$ctx.Load($upload)
$ctx.ExecuteQuery()
and I know how to edit fields/columns, this works:
...
$item["project"] = "Test Project"
$item.Update()
...
$list.Update()
$ctx.ExecuteQuery()
but I don’t know how to tie the two together. I need to get an item reference to the file I’ve uploaded so that I can then update the item/file's metadata. As you can guess, PowerShell and SharePoint are all new to me!
The following example demonstrates how to upload a file and set file metadata using SharePoint CSOM API in PowerShell:
$filePath = "C:\Users\jdoe\Documents\SharePoint User Guide.docx" #source file path
$listTitle = "Documents"
$targetList = $Context.Web.Lists.GetByTitle($listTitle) #target list
#1.Upload a file
$fci= New-Object Microsoft.SharePoint.Client.FileCreationInformation
$fci.Overwrite = $true
$fci.Content = [System.IO.File]::ReadAllBytes($filePath)
$fci.URL = [System.IO.Path]::GetFileName($filePath)
$uploadFile = $targetList.RootFolder.Files.Add($fci)
#2.Set metadata properties
$listItem = $uploadFile.ListItemAllFields
$listItem["LastReviewed"] = [System.DateTime]::Now
$listItem.Update()
$Context.Load($uploadFile)
$Context.ExecuteQuery()
#vadimGremyachev --- THANKS! Question... I have a CSV of files that I'm uploading. One of the CSV columns is a metadata tag which I'm using a hash to convert to its GUID from the termstore. of the 500 files, I have ~5 files that refuse to set the value in SPO. It does NOT throw an error. I know the GUID is correct in my hash because other documents are tagged with the shared value from the HASH.
#2.Set metadata properties
$listItem = $upload.ListItemAllFields
$listItem["LegacySharePointFolder"] = $row.LegacySharePointFolder
$listItem.Update()
$listItem["Customer"] = $TermStoreCustomerHash[$row.CUSTOMER]
$listItem.Update()
Thanks!

How to insert strings into a table with their UTF-8 encodings?

I am trying to upload some string values into an Oracle table by means of powershell. However when I upload strings directly some characters are shown up like ? in the table.
Actually, I first parse a text and retrieve some results through regex as below:
if($wiki_link -match "http:\/\/en\.wikipedia\.org\/wiki\/(.*)") {$city = $matches[1]}
Then I wanna upload this $city variable into a table as below:
[System.Reflection.Assembly]::LoadWithPartialName("System.Data.OracleClient")
$connectionString = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(Host=xxxxxxxxx)(Port=1521)))(CONNECT_DATA=(SERVER = DEDICATED) (SERVICE_NAME =xxxxx)));user id=xxxxxx;password=xxxxx"
$connection = New-Object System.Data.OracleClient.OracleConnection($connectionString)
$connection.Open()
$cmd2=$connection.CreateCommand()
$cmd2.CommandText="insert into mehmet.goo_region (city) values ('$city')"
$rdr2=$cmd2.ExecuteNonQuery()
When I apply this method, the city named Elâzığ appears as Elaz?? in the table cell.
I guess I have to convert string into UTF-8 but I could not find a solution through web.
Thanks in advance...
Try this, it should work:
$u = New-Object System.Text.UTF8Encoding
$s = $u.GetBytes("YourStringGoesHere")
$u.GetString($s) ## this is your UTF-8 string
So your code becomes
$u = New-Object System.Text.UTF8Encoding
$s = $u.GetBytes($city)
$utf8city = $u.GetString($s)

Modify xml while preserving whitespace

I'm running into several problems trying to replace an attribute in an XML file while preserving whitespace.
Attempt 1
$xml = [xml](get-content data.xml)
$xml.Path.To.Attribute = $value
set-content data.xml [String]$value
Result: Insigificant whitespace (namely newlines) are removed
Attempt 2
$xml = new-object xml
$xml.PreserveWhitespace = true
$xml.PreserveWhitespace
Result: PreserveWhitespace remains false
Attempt 3
$xml = get-content data.xml
$xml = [regex]::replace($xml, "pattern", "replacement")
set-content data.xml $xml
Result: [regex]::replace messes up the line endings
Am I taking crazy pills here?
The problems were all related: Get-Content returns lines of the text file, not the text itself. When cast back to a string, the lines are combined outright.
The best solution was to use:
$xml = [xml]([System.IO.File]::ReadAllText("data.xml"))
This isn't working because PreserveWhiteSpace is a boolean:
$xml = new-object xml
$xml.PreserveWhitespace = true
$xml.PreserveWhitespace
Use:
xml.PreserveWhitespace = $true
By default empty lines are ignored, in order to preserve them you can change PreserveWhitespace property before reading the file:
Create XmlDocument object and configure PreserveWhitespace:
$xmlDoc = [xml]::new()
$xmlDoc.PreserveWhitespace = $true
Load the document:
$xmlDoc.Load($myFilePath)
or
$xmlDoc.LoadXml($(Get-Content $myFilePath -Raw))