Reputation: 971
I want to find all instances of an element attribute that contains a certain string and change it.
Sample xml would be:
<system>
<template>
<url address="http://localhost:7888/Application/basic" />
<url address="http://localhost:7997/sdk/basic" />
<url address="http://localhost:5855/htm/ws" />
<url address="net.tcp://localhost:5256/htm" />
<url address="http://localhost:5215/htm/basic" />
<url address="http://localhost:5235/htm/ws" />
<url address="net.tcp://localhost:5256/htm" />
<url address="http://localhost:5252/Projectappmgr/basic"/>
<url address="http://localhost:5295/Projectappmgr/ws" />
</template>
</system>
I have the following code:
XmlNodeList nodelist = doc.GetElementsByTagName("url");
foreach (XmlNode node in nodelist)
{
if (node.Attributes["address"].Value.Contains("localhost"))
{
string origValue = node.Attributes["address"].Value;
string modValue = String.Empty;
Console.WriteLine("Value of original address is: " + origValue);
modValue = origValue.Replace("localhost", "newURLName");
Console.WriteLine("Value of modified address is: " + modValue);
node.Attributes["address"].InnerText = modValue;
}
}
This modifies the address' value as expected.
<url address="http://newURLName:7888/Application/basic" />
But, what I really want is to replace the entire string "localhost:7888" with newURLName
. Is there a way to specify the port numbers as wild characters since they will not all be the same as in the example xml block?
I know I need the replace value to be "localhost:xxxx", but "xxxx" is different in each instance and I'm sort of drawing a blank at the moment.
Thanks
Upvotes: 0
Views: 462
Reputation: 12226
Regular expressions should help here:
modValue = Regex.Replace(url, @"localhost(:\d+){0,1}", newUrlName)
Here you can find more exapmles. Also I would recommend using Expresso to get familiar with Regex.
Upvotes: 2
Reputation: 32323
You could use xpath to find nodes which contain your search string and then use UriBuilder
class to modify your URLs:
var xdoc = XDocument.Parse(xml);
var nodes = xdoc.XPathSelectElements("//url[contains(@address, 'localhost')]");
foreach (var node in nodes)
{
var ub = new UriBuilder(node.Attribute("address").Value);
ub.Host = "newURLName";
node.SetAttributeValue("address", ub.ToString());
}
This will get you
<system>
<template>
<url address="http://newURLName:7888/Application/basic" />
<url address="http://newURLName:7997/sdk/basic" />
<url address="http://newURLName:5855/htm/ws" />
<url address="net.tcp://newURLName:5256/htm" />
<url address="http://newURLName:5215/htm/basic" />
<url address="http://newURLName:5235/htm/ws" />
<url address="net.tcp://newURLName:5256/htm" />
<url address="http://newURLName:5252/Projectappmgr/basic" />
<url address="http://newURLName:5295/Projectappmgr/ws" />
</template>
</system>
from your XML example even without using of regex.
Upvotes: 2
Reputation: 14272
An alternative to regex would be to use a strongly typed Uri object and the UriBuilder.
var origValue = new Uri(node.Attributes["address"].Value);
var uriBuilder = new UriBuilder(origValue);
uriBuilder.Host = newHost;
uriBuilder.Port = newPort;
modValue = uriBuilder.Uri;
This may seem long winded but it is an alternative to a simple regex, gives you something that is strongly typed and allows you to validate that the Uri is actually valid (see the Uri class methods / properties). You may also be able to do the host and port number in one step, I have not played around with that.
Upvotes: 0
Reputation: 24078
Replace
modValue = origValue.Replace("localhost", "newURLName");
by
modValue = Regex.Replace(origValue, "localhost(:[0-9]+){0,1}", "newURLName");
Upvotes: 0