Я ищу XSLT или инструмент командной строки (или код C#, который может быть превращен в инструмент командной строки, и т.д.) для Windows, который сделает симпатичную печать XML. А именно, я хочу тот, который имеет способность поместить атрибуты one-to-a-line, что-то как:
<Node>
<ChildNode
value1='5'
value2='6'
value3='happy' />
</Node>
Это не должно быть ТОЧНО похожим на это, но я хочу использовать его для XML-файла, который имеет узлы с десятками атрибутов, и распространение их через несколько строк делает их легче считать, отредактировать, и различный текстом
Примечание: Я думаю, что мое предпочтительное решение является листом XSLT, я могу пройти через метод C#, хотя инструмент командной строки Windows хорош также.
Вот небольшой пример на C#, который может быть использован непосредственно в вашем коде или встроен в exe и вызван из командной строки как "myexe from.xml to.xml
":
using System.Xml;
static void Main(string[] args)
{
XmlWriterSettings settings = new XmlWriterSettings {
NewLineHandling = NewLineHandling.Entitize,
NewLineOnAttributes = true, Indent = true, IndentChars = " ",
NewLineChars = Environment.NewLine
};
using (XmlReader reader = XmlReader.Create(args[0]))
using (XmlWriter writer = XmlWriter.Create(args[1], settings)) {
writer.WriteNode(reader, false);
writer.Close();
}
}
Пример ввода:
<Node><ChildNode value1='5' value2='6' value3='happy' /></Node>
Пример вывода (обратите внимание, что вы можете удалить с помощью
settings.OmitXmlDeclaration
):
<?xml version="1.0" encoding="utf-8"?>
<Node>
<ChildNode
value1="5"
value2="6"
value3="happy" />
</Node>
Обратите внимание, что если вам нужна строка, а не запись в файл, просто поменяйте местами с StringBuilder
:
StringBuilder sb = new StringBuilder();
using (XmlReader reader = XmlReader.Create(new StringReader(oldXml)))
using (XmlWriter writer = XmlWriter.Create(sb, settings)) {
writer.WriteNode(reader, false);
writer.Close();
}
string newXml = sb.ToString();
XML Notepad 2007 может сделать это вручную ... позвольте мне посмотреть, можно ли это написать в сценарии.
Нет ... запустить его можно так:
XmlNotepad.exe a.xml
Остальное - просто нажать кнопку сохранения. Power Shell, другие инструменты могут это автоматизировать.
Просто используйте этот xslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="ISO-8859-1"/>
<xsl:param name="indent-increment" select="' '"/>
<xsl:template name="newline">
<xsl:text disable-output-escaping="yes">
</xsl:text>
</xsl:template>
<xsl:template match="comment() | processing-instruction()">
<xsl:param name="indent" select="''"/>
<xsl:call-template name="newline"/>
<xsl:value-of select="$indent"/>
<xsl:copy />
</xsl:template>
<xsl:template match="text()">
<xsl:param name="indent" select="''"/>
<xsl:call-template name="newline"/>
<xsl:value-of select="$indent"/>
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
<xsl:template match="text()[normalize-space(.)='']"/>
<xsl:template match="*">
<xsl:param name="indent" select="''"/>
<xsl:call-template name="newline"/>
<xsl:value-of select="$indent"/>
<xsl:choose>
<xsl:when test="count(child::*) > 0">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="*|text()">
<xsl:with-param name="indent" select="concat ($indent, $indent-increment)"/>
</xsl:apply-templates>
<xsl:call-template name="newline"/>
<xsl:value-of select="$indent"/>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Или, как другой вариант, вот сценарий Perl: http://software.decisionsoft.com/index.html
Существует инструмент, который может разделять атрибуты по одному в строке: xmlpp . Это сценарий Perl, поэтому вам нужно установить perl . Использование:
perl xmlpp.pl -t input.xml
Вы также можете определить порядок атрибутов, создав файл с именем attributeOrdering.txt и вызвав perl xmlpp.pl -s -t input.xml
. Для получения дополнительных опций используйте perl xmlpp.pl -h
. Надеюсь, в нем не так много ошибок, но до сих пор он работал у меня.
Вы можете реализовать простое приложение SAX, которое будет копировать все как есть
с отступом атрибуты, как вам нравится.
UPD :
SAX означает Простой API для XML
. Это модель push-анализа XML (классический пример шаблона проектирования Builder). API присутствует на большинстве текущих платформ разработки (хотя в собственной библиотеке классов .Net он отсутствует, имея интерфейс XMLReader)
Вот необработанная реализация на python, она довольно загадочная, но вы можете реализовать основную идею.
from sys import stdout
from xml.sax import parse
from xml.sax.handler import ContentHandler
from xml.sax.saxutils import escape
class MyHandler(ContentHandler):
def __init__(self, file_, encoding):
self.level = 0
self.elem_indent = ' '
# should the next block make a line break
self._allow_N = False
# whether the opening tag was closed with > (to allow />)
self._tag_open = False
self._file = file_
self._encoding = encoding
def _write(self, string_):
self._file.write(string_.encode(self._encoding))
def startElement(self, name, attrs):
if self._tag_open:
self._write('>')
self._tag_open = False
if self._allow_N:
self._write('\n')
indent = self.elem_indent * self.level
else:
indent = ''
self._write('%s<%s' % (indent, name))
# attr indent equals to the element indent plus ' '
attr_indent = self.elem_indent * self.level + ' '
for name in attrs.getNames():
# write indented attribute one per line
self._write('\n%s%s="%s"' % (attr_indent, name, escape(attrs.getValue(name))))
self._tag_open = True
self.level += 1
self._allow_N = True
def endElement(self, name):
self.level -= 1
if self._tag_open:
self._write(' />')
self._tag_open = False
return
if self._allow_N:
self._write('\n')
indent = self.elem_indent * self.level
else:
indent = ''
self._write('%s</%s>' % (indent, name))
self._allow_N = True
def characters(self, content):
if self._tag_open:
self._write('>')
self._tag_open = False
if content.strip():
self._allow_N = False
self._write(escape(content))
else:
self._allow_N = True
if __name__ == '__main__':
parser = parse('test.xsl', MyHandler(stdout, stdout.encoding))
Вот для этого сценарий PowerShell. Он принимает следующий ввод:
<?xml version="1.0" encoding="utf-8"?>
<Node>
<ChildNode value1="5" value2="6" value3="happy" />
</Node>
... и производит это как вывод:
<?xml version="1.0" encoding="utf-8"?>
<Node>
<ChildNode
value1="5"
value2="6"
value3="happy" />
</Node>
Вот и все:
param(
[string] $inputFile = $(throw "Please enter an input file name"),
[string] $outputFile = $(throw "Please supply an output file name")
)
$data = [xml](Get-Content $inputFile)
$xws = new-object System.Xml.XmlWriterSettings
$xws.Indent = $true
$xws.IndentChars = " "
$xws.NewLineOnAttributes = $true
$data.Save([Xml.XmlWriter]::Create($outputFile, $xws))
Возьмите этот сценарий и сохраните его как C: \ formatxml.ps1. Затем в командной строке PowerShell введите следующее:
C:\formatxml.ps1 C:\Path\To\UglyFile.xml C:\Path\To\NeatAndTidyFile.xml
Этот сценарий в основном просто использует платформу .NET, поэтому вы можете очень легко перенести его в приложение C #.
ПРИМЕЧАНИЕ. Если вы раньше не запускали сценарии из PowerShell, вам нужно будет выполнить следующую команду в командной строке PowerShell с повышенными привилегиями, прежде чем вы сможете выполнить сценарий:
Set-ExecutionPolicy RemoteSigned
Вам нужно сделать это только один раз.
Надеюсь, это полезно для вас.
Попробуйте Tidy на SourceForge. Хотя он часто используется в [X] HTML, я раньше успешно использовал его в XML - просто убедитесь, что вы используете параметр -xml
.
http://tidy.sourceforge.net/#docs
Tidy читает файлы HTML, XHTML и XML и записывает очищенную разметку. ...Для общих файлов XML Tidy ограничивается исправлением основных ошибок правильного формата и красивой печатью .
Люди портировали его на несколько платформ, и он доступен в виде исполняемой и вызываемой библиотеки.
В Tidy есть куча параметров , включая:
http://api.html-tidy.org/tidy/quickref_5.0.0.html#indent
атрибуты отступа
Тип верхней части: Boolean
По умолчанию: no Пример: y / n, yes / no, t / f, true / false, 1/0
Этот параметр указывает, должен ли Tidy начинать каждый атрибут с новой строки.
Одно предостережение:
Ограниченная поддержка XML
XML-процессоры, совместимые с рекомендацией W3C XML 1.0, очень разборчивы в том, какие файлы они будут принимать. Tidy может помочь вам исправить ошибки, из-за которых ваши XML-файлы отклоняются. Однако Tidy еще не распознает все функции XML, например он не понимает разделы CDATA или подмножества DTD.
Но я подозреваю, что если ваш XML не является действительно продвинутым, инструмент должен работать нормально.