Domanda

Sto modificando alcune .vcrpoj i file in .NET, ma quando ho salvare le modifiche di formattazione (che i relitti caos con il mio diff strumento), i file originali assomigliare a questo:

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

Ma quando salvo le modifiche assomiglia a questo:

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

Sto utilizzando il seguente XmlWritterSettings

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

C'è un modo per definire le impostazioni per abbinare il formato di visual studio utilizza?(Ho bisogno di NewLineOnAttributes altrimenti è anche peggio).

È stato utile?

Soluzione

Non credo che si può fare con il built-in XmlWriter realizzazione di...si potrebbe ereditare da XmlTextWriter, e l'override del metodo appropriato (non è sicuro che quello che è...) per scrivere gli elementi con il formato desiderato


Qui ci sono alcune XML-conoscenza diff strumenti (che metterà a confronto i file in base alla semantica, ignorando la formattazione) :

Con questi strumenti, non avrete bisogno di preoccuparsi per il formato XML è possibile generare

Altri suggerimenti

Importa?Presumibilmente l' .NET IDE legge lo standard XML.Tutto ciò che conta è che il vostro XML è legale, e a quanto pare è.Hai davvero un problema?

EDIT:(Un altro utente indica il vero problema è con diff ing).Diciamo, indipendentemente dal processo che si sta utilizzando per produrre il nuovo risultato P, con il vecchio file F.Se si esegue P(F) che è, semplicemente leggi di F e scrivere di nuovo senza alcuna modifica, si otterrà il tuo nuovo (scomodo) formato di file originale.

Sto cercando di indovinare che cosa si sta facendo l'esecuzione di P(F+epsilon), dove si sta modificando l'originale F con epsilon modifiche, e la produzione di questo, e quindi si hanno difficoltà a confrontare il nuovo con l'originale.Un modo per risolvere questo problema, è semplicemente eseguire P(F) in originale, e confrontarlo con P(F+epsilon).Ora, presumibilmente, gli stili di formattazione di entrambi sono identici e i tuoi cambiamenti sarà ragionevole.Questo tipo di stunt è chiamato "normalizzazione".

L'altra alternativa è quella di eseguire un diff strumento che capisce XML, e quindi sa che cosa la formattazione è irrilevante.

Anche WinMerge (gratuito, GPL), con il plugin xml

Magari cambiando il diff strumento di risolvere i vostri problemi, come tutto il resto a quanto pare funziona bene.Alcuni diff strumenti come WinMerge hanno un opzione per filtrare quali sono le differenze che si desidera ignorare, anche è in grado di fornire una espressione regolare per definire la regola

Iniziare da saveing indietro xml, leggere e riscrivere con una versione modificata del metodo seguito per iniettare la line-feed e schede.Per fare questo, è possibile ottenere la scheda di conteggio utilizzando rdr.La profondità e l'uso wtr.WriteRaw(" " + new String(' ', tabCount)) appena prima di chiamare il WriteEndElement) per scrivere non significativo spazio bianco.Mi dispiace, questo è il codice non TESTATO, ma è il più vicino che posso ottenere.

    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)
                );
        }
    }

XmlWriter.Creare restituisce una specifica XmlRawWriter avvolto in un XmlWellFormedWriter, tutti definiti come interno in modo è possibile estendere la loro.

Tuttavia, è possibile estendere XmlTextWriter, ma è un insieme di funzionalità limitate rispetto alla ben formata scrittore.

Quindi...

Qui è un custom XmlTextWriter ho fatto per affrontare questo problema, che ha la maggior parte delle caratteristiche che mancano da ben formata scrittore, e stralci XmlWriterSettings:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace System.Xml
{
    public class CustomXmlTextWriter : XmlTextWriter
    {
        internal class CustomStreamWriter : StreamWriter
        {
            public CustomStreamWriter(Stream stream, Encoding encoding) : base(stream) { }
            // This prevents the XmlTextWriter from writing the extra space before attributes, and the short EndElement " />"
            public bool DisableSpace { get; set; }
            public override void Write(char value)
            {
                if (DisableSpace && value == ' ') return;
                else base.Write(value);
            }
            public override void Write(string value)
            {
                if (DisableSpace && value == " /") base.Write('/');
                else base.Write(value);
            }
        }

        public CustomXmlTextWriter(string filename, XmlWriterSettings settings) : this(new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read), settings) { }
        public CustomXmlTextWriter(Stream stream, XmlWriterSettings settings) : this(new CustomStreamWriter(stream, settings.Encoding), settings) { }
        internal CustomXmlTextWriter(CustomStreamWriter writer, XmlWriterSettings settings)
            : base(writer)
        {
            m_Writer = writer;
            m_Settings = settings;

            if (m_Settings.OmitXmlDeclaration == false)
            {
                string encoding = (m_Writer.Encoding.CodePage == 1201) ? "UTF-16BE" : m_Writer.Encoding.WebName;
                m_Writer.WriteLine("<?xml version=\"1.0\" encoding=\"{0}\"?>", encoding);
            }
        }

        private bool m_HasAttributes = false;
        private Stack<bool> m_HasAttributesStack = new Stack<bool>();
        private CustomStreamWriter m_Writer;
        private XmlWriterSettings m_Settings;

        public override XmlWriterSettings Settings { get { return m_Settings; } }

        public override void WriteStartElement(string prefix, string localName, string ns)
        {
            if (WriteState == WriteState.Element)
            {
                if (m_HasAttributes && Settings.NewLineOnAttributes) { WriteIndent(m_HasAttributesStack.Count); }
                WriteRaw(""); // Trick the XmlTextWriter into closing the previous element, and updating the WriteState
                m_Writer.DisableSpace = false;
            }
            int indentLevel = m_HasAttributesStack.Count;
            if (indentLevel > 0)
            {
                WriteIndent(indentLevel);
            }
            m_HasAttributesStack.Push(m_HasAttributes);
            m_HasAttributes = false;

            base.WriteStartElement(prefix, localName, ns);
        }

        public override void WriteEndElement()
        {
            if (m_HasAttributes && Settings.NewLineOnAttributes)
            {
                WriteIndent(m_HasAttributesStack.Count - 1);
            }
            m_HasAttributes = m_HasAttributesStack.Pop();
            base.WriteEndElement();

            m_Writer.DisableSpace = false;
        }

        public override void WriteFullEndElement()
        {
            m_HasAttributes = m_HasAttributesStack.Pop();
            WriteIndent(m_HasAttributesStack.Count);
            base.WriteFullEndElement();
        }

        public override void WriteStartAttribute(string prefix, string localName, string ns)
        {
            if (Settings.NewLineOnAttributes)
            {
                WriteIndent(m_HasAttributesStack.Count);
                m_Writer.DisableSpace = true;
            }
            m_HasAttributes = true;
            base.WriteStartAttribute(prefix, localName, ns);
        }

        public override void WriteString(string text)
        {
            if (m_Settings.NewLineHandling == NewLineHandling.Replace)
            {
                text = Regex.Replace(text, @"\r\n?|\n", m_Settings.NewLineChars);
            }
            else if (m_Settings.NewLineHandling == NewLineHandling.Entitize)
            {
                text = Regex.Replace(text, @"\n|\r", m => String.Format("&#x{0:X};", (int)m.Value[0]));
            }
            base.WriteString(text);
        }

        private void WriteIndent(int indentLevel)
        {
            if (Settings.Indent == false) return;
            m_Writer.Write(Settings.NewLineChars);
            for (int i = 0; i < indentLevel; ++i)
            {
                m_Writer.Write(Settings.IndentChars);
            }
        }
    }
}

Basta fare un file contenente il codice di cui sopra il vostro progetto, e quindi utilizzarlo in questo modo:

        // Create the XmlWriter Settings as you normally would
        // *Note: You can change or omit these, they are just for an example of what I supported
        XmlWriterSettings settings = new XmlWriterSettings()
        {
            Encoding = Encoding.UTF8,
            //OmitXmlDeclaration = true,
            Indent = true,
            //IndentChars = "  ",
            IndentChars = "\t",
            NewLineOnAttributes = true,
            //NewLineHandling = NewLineHandling.Entitize,
            //NewLineHandling = NewLineHandling.Replace,
            //NewLineChars = @"\n",
        };

        // Replace XmlWriter.Create with new CustomXmlTextWriter
        //using (XmlWriter writer = XmlWriter.Create(path, settings))
        using (XmlWriter writer = new CustomXmlTextWriter(path, settings))
        {
            xml.WriteTo(writer);
        }

Sarebbe bello se questa funzionalità sono stati appena aggiunti a ben formata scrittore come opzione in XmlWriterSettings.

A volte cambiando la diff strumento non è un'opzione (o anche il problema in primo luogo) Quando si usano sistemi come necessariamente auto unire le modifiche tramite uno strumento, è meglio mantenere le modifiche atomic possibile.

Per esempio...Se l'ultimo attributo è cambiato di una sola persona, e un attributo aggiuntivo viene aggiunto alla fine di un'altra persona, non c'è motivo di creare un artificiale conflitto sulla base di una linea che dovrebbe contenere la chiusura > (o />).La soluzione migliore per questo scenario è se la parentesi di chiusura è sulla sua linea, e di evitare il conflitto, tutti insieme.

Suona come si sta modificando un sacco di file, quindi questo non può essere pratico, ma aprendo il file in VS e risparmio dovrebbe ripristinare la formattazione standard.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top