views:

476

answers:

7

I'm modifying some .vcrpoj files in .NET but when I save them the formatting changes (which wrecks havoc with my diff tool), the original files look like this:

<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
>
<Platforms>
 <Platform
  Name="Win32"
 />
</Platforms>
<ToolFiles>
</ToolFiles>

But when I save the changes it looks like this:

<VisualStudioProject
ProjectType="Visual C++"
Version="8.00">
<Platforms>
 <Platform
  Name="Win32" />
</Platforms>
<ToolFiles></ToolFiles>

I'm using the following XmlWritterSettings

XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = ("\t");
settings.Encoding = Encoding.UTF8;
settings.NewLineOnAttributes = true;

Is there a way to define the settings in order to match the format visual studio uses? (I need NewLineOnAttributes otherwise it's even worse).

+6  A: 

I don't think you can do it with the built-in XmlWriter implementation... you could inherit from XmlTextWriter, and override the appropriate method (not sure which one it is...) to write elements with the desired format


Here are a few XML-aware diff tools (that will compare the files based on semantics, ignoring the formatting) :

With those tools, you won't need to worry about the XML format you generate

Thomas Levesque
Can you be more specific? When inheriting from `XmlWriter` I don't even see how to construct my `base` (when working with the built in implementation I use the static `.Create` method but how do I pass this to my `base`?).
Motti
The XmlWriter constructor is protected, so you can call it from a derived class. However, it would be easier to inherit directly from XmlTextWriter, so that you don't have to code everything from scratch
Thomas Levesque
I gave it a try, and it doesn't seem possible to do that without a lot of code... Anyway, if your only problem with the formatting is the diff tools, I suggest that you use a tool that understands XML, and compare the semantics, not just the text. If you use Beyond Compare, there is a plugin that formats both documents with Tidy before comparing them.
Thomas Levesque
Yeah I tried and failed with `XmltextWriter` too, thanks for the pointers though.
Motti
+2  A: 

Does it matter? Presumably the .NET IDE reads standard XML. All that counts is that your XML is legal, and apparantly it is. Do you really have a problem?

EDIT: (Another user indicates the real problem is with diff'ing). Let's call whatever process you are using to produce your new result P, with the old file being F. If you run P(F) that is, simply read F and write it back out without any changes, you'll get your new (inconvenient) format on the original file.

I'm guessing what you are doing is running P(F+epsilon), where you are modifying the original F with epsilon changes, and producing this, and then you have difficulty comparing the new with the original. One way to solve this problem is to simply run P(F) on the original, and compare it with P(F+epsilon). Now presumably the formatting styles of both are identical and your diffs will be reasonable. This kind of stunt is called "normalization".

The other alternative is to run a diff tool that understands XML, and thus knows what formatting is irrelevant.

Ira Baxter
read the question again: "when I save them the formatting changes (**which wrecks havoc with my diff tool**)"
Thomas Levesque
+1 for XML aware diff tool
Rob Fonseca-Ensor
+1  A: 

Also WinMerge (free, GPL), with the xml plugin

ja
+1  A: 

Modify my Pretty Diff tool. It does everything you need already except beautify the code in the manner that you want. The tool is basically a diff tool that takes two code bits and minifies then and then beautifies them before performing the diff. This removes differences due to comments, extraneous white-space, and minification. The diff engine visually highlights the differences per character and per line.

It is written entirely in JavaScript so it can be run from your browser, or you can run it from a command line using Rhino for Java, but running it from the command line will lose the visual benefits of executing it from the browser. Check out the tool to determine if this works for you. You will want to diff using the "Markup" mode, which is written to support vocabulary independent XML.

http://mailmarkup.org/prettydiff/prettydiff.html

+1  A: 

Maybe changing your diff tool will solve your problems, as everything else apparently runs fine. Some diff tools like WinMerge have a option to filter what differences you want to ignore, even you can supply a regular expression to define the rule

Rodrigo
+1  A: 

Start by saveing it back to xml, read and rewrite with a modified version of the method below to inject the line-feeds and tabs. To do this you can get the tab count by using rdr.Depth and use wtr.WriteRaw("\r\n" + new String('\t', tabCount)) just before you call the WriteEndElement) to write the non-significant white space. Sorry, this is UNTESTED code but it is as close as I can get you.

 public void CopyXmlContentsToFile(XmlTextReader rdr, XmlTextWriter wtr)
 {
  try
  {
   rdr.WhitespaceHandling = WhitespaceHandling.Significant;
   wtr.Formatting = Formatting.Indented;
   CopyNodes(rdr, wtr);
  }
  finally
  {
   rdr.Close();
   wtr.Close();
  }
 }


 void CopyNodes(XmlReader rdr, XmlWriter wtr)
 {
  if (rdr.NodeType == XmlNodeType.Text || rdr.NodeType == XmlNodeType.SignificantWhitespace)
  {
   wtr.WriteString(rdr.Value);
  }
  else if (rdr.NodeType == XmlNodeType.Whitespace)
   return;
  else if (rdr.NodeType == XmlNodeType.Element)
  {
   string elemName = rdr.LocalName;
   bool empty = rdr.IsEmptyElement;

   wtr.WriteStartElement(elemName);

   while (rdr.MoveToNextAttribute())
   {
    if (rdr.Prefix.Length == 0)
     wtr.WriteAttributeString(rdr.LocalName, rdr.Value);
   }

   if (rdr.NodeType == XmlNodeType.Attribute)
    rdr.MoveToElement();

   if (!empty)
   {
    while (rdr.Read() && rdr.NodeType != XmlNodeType.EndElement)
     CopyNodes(rdr, wtr);
   }

   if (!empty && wtr.WriteState != WriteState.Content)
    wtr.WriteRaw("");

   if (!empty)
   {
    //Here we can inject our custom formatting with WriteRaw():
    wtr.WriteRaw(Environment.NewLine + new String('\t', rdr.Depth));
   }

   wtr.WriteEndElement();
  }
  else
  {
   throw new ApplicationException(
    String.Format("Unexpected node type {0} at line {1}.", rdr.NodeType, ((XmlTextReader)rdr).LineNumber)
    );
  }
 }
csharptest.net
A: 

It sounds like you're modifying a lot of files, so this may not be practical, but opening the file in VS and saving it should restore the standard formatting.

Abraham Pinzur