У нас есть конвейер обмена сообщениями, который включает преобразования XML в XML.
Для такого исходного документа (который также может быть в одной строке без форматирования):
<doc>
<a>Foo</a>
<b>Bar1</b>
<b>Bar2</b>
<b>Bar3</b>
<c>Baz</c>
</doc>
Мне нужен вывод XML преобразования (обратите внимание на разрывы строк):
<x>Bar1
Bar2
Bar3</x>
Но вывод, который я получаю:
<x>Bar1Bar2Bar3</x>
Таблица стилей выглядит следующим образом:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<x>
<xsl:for-each select="//b">
<xsl:value-of select="." />
<xsl:if test="position() != last()">
<xsl:text>
</xsl:text> <!-- something wrong here? -->
</xsl:if>
</xsl:for-each>
</x>
</xsl:template>
</xsl:stylesheet>
Если я добавлю непробельный символ к текстовому узлу, я получу сохранение новой строки. Итак, если я изменю узел xsl:text
на (обратите внимание на добавленный дефис):
<xsl:text>-
</xsl:text>
тогда я получаю вывод:
<x>Bar1-
Bar2-
Bar3</x>
Как я могу сгенерировать желаемый результат?
Обратите внимание, что мы ограничены XSLT 1.0.
Обновление
Я сделал еще несколько тестов. Ниже приведен полный код для воспроизведения проблемы. Интересно, что этот код воспроизводит проблему при запуске под .Net Framework 4.5 и .Net Core 2.1, но он дает желаемый результат при запуске под Mono.
using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
namespace xslt
{
class Program
{
static void Main(string[] args)
{
var doc = new XmlDocument();
doc.LoadXml(@"<doc><a>Foo</a><b>Bar1</b><b>Bar2</b><b>Bar3</b><c>Baz</c></doc>");
var xsl = new XmlDocument();
xsl.LoadXml(@"<?xml version='1.0' encoding='utf-8'?>
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
<xsl:output omit-xml-declaration='yes' method='xml' version='1.0' />
<xsl:template match='/'>
<x>
<xsl:for-each select='//b'>
<xsl:value-of select='.' />
<xsl:if test='position() != last()'>
<xsl:text>
</xsl:text> <!-- something wrong here? -->
</xsl:if>
</xsl:for-each>
</x>
</xsl:template>
</xsl:stylesheet>");
var xslt = new XslCompiledTransform();
xslt.Load(xsl);
using (var stream = new MemoryStream())
{
xslt.Transform(doc, null, stream);
Console.WriteLine(Encoding.UTF8.GetString(stream.ToArray()));
}
}
}
}