Paul
Paul

Reputation: 971

C# How to modify xml attributes based on searched string

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

Answers (4)

the_joric
the_joric

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

Oleks
Oleks

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

Bronumski
Bronumski

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

dee-see
dee-see

Reputation: 24078

Replace

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

by

modValue = Regex.Replace(origValue, "localhost(:[0-9]+){0,1}", "newURLName");

Upvotes: 0

Related Questions