0

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

Chris Barlow
  • 3,274
  • 4
  • 31
  • 52
Paul
  • 891
  • 1
  • 6
  • 10

4 Answers4

2

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.

the_joric
  • 11,986
  • 6
  • 36
  • 57
2

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.

Community
  • 1
  • 1
Oleks
  • 31,955
  • 11
  • 77
  • 132
  • Great minds and all that. One thing I wasn't sure of without playing is can you set the host and port number at the same time by setting the host name with a string that contains the hostname and the portnumber i.e. uriBuilder.Host = "newhost:80"; – Bronumski Mar 15 '12 at 23:12
  • @Bronumski, nope. It'll threat `hewhost:portnumber` as a *host* only; so the previous portnumber will be appended like this: `http://[newURLName:777]:7888/Application/basic`. – Oleks Mar 15 '12 at 23:16
  • Shame, always looking for the one liner. Thanks for the feedback though. – Bronumski Mar 15 '12 at 23:18
0

Replace

modValue = origValue.Replace("localhost", "newURLName");

by

modValue = Regex.Replace(origValue, "localhost(:[0-9]+){0,1}", "newURLName");
dee-see
  • 23,668
  • 5
  • 58
  • 91
0

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.

Bronumski
  • 14,009
  • 6
  • 49
  • 77
  • Thanks. New to programming. Have not dealt with Uri, but will definitely look into it. – Paul Mar 15 '12 at 23:12