3

I need to write a small console application that takes an XAML file as a parameter, and then makes a copy of it with 2 modifications:

1) All Text attributes are set to the string "example" (not on every tag, only where they were actually set to something else)

2) All tags that contain the attribute Header, will have a header template inside the tag instead. For example, this:

<GridViewColumn Header="example">
    <!-- Some other stuff... -->
</GridViewColumn>

Should be changed to this:

<GridViewColumn>
    <GridViewColumn.HeaderTemplate>
       <DataTemplate>
           <TextBlock Text="example"/>
       </DataTemplate>
</GridViewColumn>

I was thinking of using Regex for the logic, but I want to know if there's an easier way to do this?

Drake
  • 2,679
  • 4
  • 45
  • 88

1 Answers1

2

Using proper XML parser to modify XML would be more robust, because decent XML parser will never produce non well-formed XML, besides regex is not the tool for parsing XML in general.

Because you haven't started anything with any XML parser -or looks like so-, the following is just for the sake of illustration of how this can be done using XML parser, LINQ-to-XML to be specific.

Consider the following XAML and predefined data template :

var xaml = @"<StackPanel>
    <TextBlock Text='not example'/>
    <!-- Some other stuff... -->
    <GridViewColumn Header='example'>
        <!-- Some other stuff... -->
    </GridViewColumn>
</StackPanel>";
var templateXaml = @"<DataTemplate>
    <TextBlock Text='example'/>
</DataTemplate>";
var doc = XDocument.Parse(xaml); //or load from file: XDocument.Load("path-to-XAML.xaml");
var template = XElement.Parse(templateXaml);

To apply modification no.1, you can simply do as follow :

foreach (var attr in doc.Descendants().Attributes("Text").Where(o => o.Value != "example"))
{
    attr.Value = "example";
}

and the following for modification no.2 :

foreach (var element in doc.Descendants().Where(o => o.Attribute("Header") != null))
{
    //delete all existing content
    element.DescendantNodes().Remove();
    //add new content element named "ParentElementName.HeaderTemplate"
    element.Add(new XElement(element.Name.LocalName + ".HeaderTemplate", template));
}
//print the modified XDocument (or save to file instead)
Console.WriteLine(doc.ToString());

Dotnetfiddle Demo

console output :

<StackPanel>
  <TextBlock Text="example" />
  <!-- Some other stuff... -->
  <GridViewColumn Header="example">
    <GridViewColumn.HeaderTemplate>
      <DataTemplate>
        <TextBlock Text="example" />
      </DataTemplate>
    </GridViewColumn.HeaderTemplate>
  </GridViewColumn>
</StackPanel>
Community
  • 1
  • 1
har07
  • 88,338
  • 12
  • 84
  • 137