2015-01-25 2 views
2

Я пытаюсь «красиво» XML-файл. Как было отмечено в некоторых других SO вопросов, я использую следующую таблицу стилей для преобразования:XSLT indent не работает с MSXML

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output indent="yes" method="xml" encoding="UTF-16" /> 
<xsl:strip-space elements="*"/> 
<xsl:template match="node() | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node() | @*" /> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

Однако это не производит желаемых результатов. Для входного файла:

<A><B><C /></B></A> 

сгенерированного выходе:

<?xml version="1.0" encoding="UTF-16"?> 
<A> 
<B> 
<C> 
</C> 
</B> 
</A> 

Но выход я ожидаю это (строка заголовка не имеет значения):

<A> 
    <B> 
     <C /> 
    </B> 
</A> 

Так являются две проблемы:

  • Нет отступов в o utput
  • Тег <C /> был «распакован», что я не хочу.

Я попытался с MSXSL.exe, и с помощью (с помощью C++) IXMLDOMDocument2::transformNode вывода на BSTR, оба метода дают идентичный выход.

Что здесь не так?

+1

Утилита MSXSL.exe составляет 11 лет. 'IXMLDOMDocument2' также чрезвычайно стар. Я бы предложил создать вашу собственную простую утилиту, используя ['XmlCompiledTransform'] (https://msdn.microsoft.com/en-us/library/system.xml.xsl.xslcompiledtransform (v = vs.110) .aspx). Это рекомендуемый .NET API для выполнения XSLT и, безусловно, будет обрабатывать отступы правильно. Вы также можете использовать что-то вроде Saxon, но текущую версию для XSLT 2.0, и вы можете столкнуться с некоторыми проблемами совместимости, если вы пишете XSLT 1.0. – JLRishe

+0

@JLRishe Моя цель - сделать это программно с C++ (не .NET), есть ли версия COM этого (или иначе)? MSXSL - это всего лишь 25 КБ, поэтому предположительно это просто выгрузка на другой объект Windows, который должен быть обновлен. –

+1

Да, MSXSL.exe - это всего лишь оболочка для нескольких различных COM-интерфейсов для XSLT (вы можете получить исходный код утилиты из указанной вами ссылки и посмотреть файл msxmlinf.cxx), который, скорее всего, не был обновлен в 11 года. Боюсь, я не знаю лучшего варианта для COM. Обычно я не работаю с COM или собственным кодом. – JLRishe

ответ

2

Следующая WSH (Windows Scripting Host) Программа JScript с использованием MSXML 6.0 (который доступен на всех поддерживаемых ОС Microsoft по умолчанию, без установки) выводит

<?xml version="1.0" encoding="UTF-16"?> 
<A> 
     <B> 
       <C></C> 
     </B> 
</A> 

Программа

var msxmlVersion = '6.0'; 
var xml = new ActiveXObject('Msxml2.DOMDocument.' + msxmlVersion); 
xml.async = false; 
xml.load('test2015012501.xml'); 

var xsl = new ActiveXObject('Msxml2.DOMDocument.' + msxmlVersion); 
xsl.async = false; 
xsl.load('test2015012501.xsl'); 

var resultDoc = new ActiveXObject('Msxml2.DOMDocument.' + msxmlVersion); 

xml.transformNodeToObject(xsl, resultDoc); 

WScript.Echo(resultDoc.xml); 

вход и XSLT - ваши образцы. Таким образом, используя MSXML 6.0 и transformNodeToObject, вы получаете лучшие результаты отступов, хотя для моих потребностей в отступе используется слишком много символов отступа.

Конечно, вместо использования JScript вы сможете использовать MSXML 6 с C++ и получать те же результаты.

И если вы хотите файл вместо строки, вы можете, конечно, использовать resultDoc.save('file.xml').

+0

Вместо 'WScript.Echo (resultDoc.xml)' Я думаю, что явным образом рекомендую 'resultDoc.save ('outFile.xml')' лучше, потому что это уменьшает опасность использования людьми FileSystemObject/TextStream для сохранения XML и потенциального использования проблемы с кодировкой файлов. – Tomalak

+0

как насчет вопроса '' заменяется на ''? –

+0

В XML '' и '', а также '' все разметки с той же семантикой, а именно с элементом 'C' без дочерних узлов, поэтому изменение разрешено. Результат, который вы получили с пробелами или разрывами строк, вставленными в ранее пустой элемент, является ошибкой в ​​моем представлении. –