Программно форматируйте XML с отступом, как в автоматическом формате Visual Studio - PullRequest
6 голосов
/ 22 ноября 2010

Я не нашел способа использовать .NET XmlWriter и связанные с ним XmlWriterSettings для форматирования строки XML с отступом в точности так, как это делает Visual Studio с помощью команды автоформатирования (Ctrl-E Ctrl-D или, в зависимости отпри раскладке клавиатуры Ctrl-K Ctrl-D).

Я хотел бы сделать это, потому что я обычно автоматически форматирую все свои файлы в VS, как файлы кода, так и файлы .config.У меня есть приложение-установщик, которое обновляет файлы .config, и я хотел бы видеть измененные различия вместо всего документа.

Я не исследовал все различные параметры форматирования для автоматического форматирования, но мне нравитсякаждый атрибут XML должен находиться на отдельной строке, причем первый находится на той же строке, что и открывающий тег, а последующие - на первом, например:

<asset assetId="12345"
       bucket="default"
       owner="nobody">
  <file path="\\localhost\share\assetA.mov"/>
  <metadata metadataId="23456"
            key="asset_type"
            value="video"/>
</asset>

Я попытался отформатировать со свойствами XmlWriterSettings'NewLineHandling = NewLineHandling.None' и 'NewLineOnAttributes = true', но это помещает первый атрибут ниже открывающего тега, и все атрибуты имеют одинаковый отступ независимо от количества символов в имени элемента, например:

<asset
  assetId="12345"
  bucket="default"
  owner="nobody">
  <file
    path="\\localhost\share\assetA.mov" />
  <metadata metadataId="23456"
    key="asset_type"
    value="video" />
</asset>

Обратите внимание, что стандартный XmlWriter также заканчивает элементы только для атрибута символом "/>" (лишний пробел перед косой чертой), что мне не нравится, но я не уверен, является ли это стандартом XML.Я думаю, что Visual Studio использует те же параметры API, которые легко доступны разработчикам, но я пока не нашел этих волшебных настроек.В любом случае, вот мой метод форматирования:

public static string FormatXml( string xmlString, bool indented )
{
    using ( TextReader textReader = new StringReader( xmlString ) )
    using ( XmlReader xmlReader = new XmlTextReader( textReader ) )
    {
        using ( TextWriter textWriter = new StringWriter() )
        {
            var settings = new XmlWriterSettings();
            if ( indented )
            {
               settings.Indent = true;
               settings.IndentChars = "  ";
               settings.NewLineOnAttributes = true;
               settings.NewLineHandling = NewLineHandling.None;
            }
            using ( var xmlWriter = XmlWriter.Create( textWriter, settings ) )
            {
                while ( xmlReader.Read() )
                    xmlWriter.WriteNode( xmlReader, false );
            }
            return textWriter.ToString();
        }
    }
}

Ответы [ 3 ]

1 голос
/ 22 ноября 2010

Я неправильно понял вопрос. На самом деле я не знаю, есть ли способ выровнять атрибуты так, как вы показали. Вы можете попробовать реализовать это самостоятельно, примерно так:

    public static string FormatXml(string xmlString, bool indented)
    {
        using (TextReader textReader = new StringReader(xmlString))
        using (XmlReader xmlReader = new XmlTextReader(textReader))
        {
            using (TextWriter textWriter = new StringWriter())
            {
                string indent = "";
                string attributeIndent = "";

                while (xmlReader.Read())
                {
                    if (xmlReader.NodeType == XmlNodeType.Element)
                    {
                        attributeIndent = "";
                        string element = xmlReader.Name;
                        textWriter.Write("{0}<{1}", indent, element);

                        if (!xmlReader.HasAttributes)
                            textWriter.WriteLine(">");
                        else
                        {
                            int actual = 1;
                            while (xmlReader.MoveToNextAttribute())
                            {
                                string content = String.Format("{0} {1}={2}", attributeIndent, xmlReader.Name, xmlReader.Value);
                                if (actual != xmlReader.AttributeCount)
                                    textWriter.WriteLine(content);
                                else
                                    textWriter.Write(content);

                                if (string.IsNullOrEmpty(attributeIndent))
                                    attributeIndent = indent + Enumerable.Repeat<string>(" ", element.Length + 1).Aggregate((a, b) => a + b);

                                actual++;
                            }
                            xmlReader.MoveToElement();
                            textWriter.WriteLine(">");
                            attributeIndent = "";
                        }
                        if (!xmlReader.IsEmptyElement)
                        {
                            indent += "  ";
                            textWriter.WriteLine(">");
                        }
                        else
                            textWriter.WriteLine("/>");
                    }
                    else if (xmlReader.NodeType == XmlNodeType.EndElement)
                    {
                        indent = indent.Substring(0, indent.Length - 2);
                        textWriter.WriteLine("{0}</{1}>", indent, xmlReader.Name);
                    }
                    else if (xmlReader.NodeType == XmlNodeType.Text)
                    {
                        textWriter.WriteLine(xmlReader.Value);
                    }
                }

                return textWriter.ToString();
            }
        }
    }
0 голосов
/ 31 декабря 2010

Я думаю, что кавычки являются недействительными xml, что может вызвать у читателя / писателя изжогу. Кроме этого, почему бы вам просто не указать приложению diff игнорировать пробелы?

0 голосов
/ 13 декабря 2010

См. Ответ здесь: Существует ли таблица стилей или инструмент командной строки Windows для управляемого форматирования XML, в частности, для атрибутов, устанавливаемых по одной на строку?

Это близко, но основное отличие с первого взгляда в том, что первый атрибут находится на новой строке, тогда как в Visual Studio он остается на той же строке, что и имя элемента.

...