2015-02-05 2 views
1

Я использую Saxon HE 9.5.1.8 для преобразования XML в другой файл XML.Saxon XSLT: Serializer производит странные отступы

Моя проблема заключается в том, что содержимое XML, написанное классом Serializer() Saxon, распечатывает несколько дополнительных отступов, которые я не хочу иметь там. Я предполагаю, что это «неправильно», потому что я получил ожидаемый результат при использовании класса DomDestination() (но тогда отсутствует информация о внешнем XML-документе) или других трансформаторов XSL, таких как тот, который поставляется с Visual Studio/.NET Фреймворк.

Это входной XML:

<?xml version="1.0"?> 
<catalog> 
    <book id="bk101"> 
    <author>Gambardella, Matthew</author> 
    <title>XML Developer's Guide</title> 
    <genre>Computer</genre> 
    <price>$44.95</price> 
    <publish_date>2000-10-01</publish_date> 
    </book> 
    <book id="bk102"> 
    <author>Ralls, Kim</author> 
    <title>Midnight Rain</title> 
    <genre>Fantasy</genre> 
    <price>$5.95</price> 
    <publish_date>2000-12-16</publish_date> 
    </book> 

Это файл XLST:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="@* | node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="book"> 
    <book> 
     <xsl:copy-of select="@*|book/@*" /> 
     <xsl:for-each select="*"> 
     <xsl:attribute name="{name()}"> 
      <xsl:value-of select="text()"/> 
     </xsl:attribute> 
     </xsl:for-each> 
    </book> 
    </xsl:template> 

</xsl:stylesheet> 

Это ожидаемый результат:

<?xml version="1.0" encoding="utf-8"?> 
<catalog> 
    <book id="bk101" author="Gambardella, Matthew" title="XML Developer's Guide" genre="Computer" price="$44.95" publish_date="2000-10-01" /> 
    <book id="bk102" author="Ralls, Kim" title="Midnight Rain" genre="Fantasy" price="$5.95" publish_date="2000-12-16" /> 
</catalog> 

И это выход при использовании Saxon:

<?xml version="1.0" encoding="UTF-8"?> 
<catalog> 
    <book id="bk101" 
     author="Gambardella, Matthew" 
     title="XML Developer's Guide" 
     genre="Computer" 
     price="$44.95" 
     publish_date="2000-10-01"/> 
    <book id="bk102" 
     author="Ralls, Kim" 
     title="Midnight Rain" 
     genre="Fantasy" 
     price="$5.95" 
     publish_date="2000-12-16"/> 
</catalog> 

Кто-нибудь знает, как подавить или изменить это поведение саксонского? То есть код # C, который используется для вызова API Saxon:

public Stream Transform(string xmlFilePath, string xsltFilePath) 
{ 
    var result = new MemoryStream(); 

    var xslt = new FileInfo(xsltFilePath); 
    var input = new FileInfo(xmlFilePath); 

    var processor = new Processor(); 
    var compiler = processor.NewXsltCompiler(); 
    var executable = compiler.Compile(new Uri(xslt.FullName)); 

    var destination = new Serializer(); 
    destination.SetOutputStream(result); 

    using(var inputStream = input.OpenRead()) 
    { 
     var transformer = executable.Load(); 
     transformer.SetInputStream(inputStream, new Uri(input.DirectoryName)); 
     transformer.Run(destination); 
    } 
    result.Position = 0; 
    return result; 
} 
+1

Это семантически эквивалентно документу, который не имеет отступов таким образом. Почему это проблема? – Flynn1179

+0

Идея состоит в том, чтобы иметь единичный тест, который проверяет выходные данные различных трансформаторных реализаций на ожидаемый результат.Я мог бы сделать тест более умным, например, прочитав вывод в XmlDocument и проверив его достоверность, но это не обязательно, если двигатели преобразования производят одни и те же результаты. –

+1

@ DanielLemke FYI, разные двигатели преобразования не * ожидаются * для получения (лексически) идентичных результатов. –

ответ

1

Ваша цель иметь несколько процессоров, производящих вывод в том же формате, безнадежно ошибочна. Это особенно важно, если вы выберете отступы вывода: спецификация полностью исключает его реализации, как делать отступы, говоря только о том, что цель состоит в том, чтобы сделать его понятным для человека. (И установка ограничений на то, где могут быть вставлены дополнительные пробелы.)

Прошу прощения, вы не нашли способ Саксона обматывать длинный список атрибутов приятным, но он полностью соответствует букве и духу спецификации. Без него, если у вас есть элемент с восемью объявлениями пространства имен, вы можете легко получить строку длиной 400 символов, которую я, конечно же, не считаю правдоподобной.

Существует много причин, по которым лексически сравнивать два документа XML, никогда не будет работать. Например, атрибуты могут быть в другом порядке. Существует два способа сравнения XML: конвертировать документы в каноническую форму с использованием процессора «Canonical XML» или сравнивать их на уровне дерева, например, используя функцию глубокого равенства() XPath 2.0. В идеале (особенно если вы хотите знать, где различия, а не только различия существуют), используйте инструмент сравнения XML-специалистов, такой как DeltaXML.

Для чего стоит, когда мы проводим модульное тестирование, мы сначала пытаемся провести лексическое сравнение результатов. Если это не удается, мы анализируем оба документа и сравниваем их с использованием saxon: deep-equal(), который является модифицированной формой функции deep-equal(), которая дает прекрасный контроль над правилами сравнения, например. обработка пробелов и обработка пространств имен.

2

Попробуйте установить http://saxonica.com/documentation9.5/extensions/output-extras/line-length.html на очень большое значение, чтобы избежать этого атрибуты помещаются на новую строку: <xsl:output xmlns:saxon="http://saxon.sf.net/" saxon:line-length="1000"/>.

+0

Хм .. это потребует введения чисто саксонского определения в файл XLST ... Если есть возможность настроить трансформатор на уровне кода, я бы предпочел пойти таким путем. –

+0

Ты работаешь с .NET или с помощью Java-версии Saxon? –

+0

.NET, но насколько я знаю, я могу использовать те же настройки для изменения вывода Serializer. Варианты описаны здесь, но я не нашел правильного: http://www.saxonica.com/html/documentation/javadoc/net/sf/saxon/s9api/Serializer.Property.html –

Смежные вопросы