使用SaxonCS执行XSLT转换时输出出现多余换行,如何解决?
问题:XSLT转换后输出多余换行,及Serializer与直接ToString()的区别
原始XML文档
<DetailBill> <DetailBillInfo> <NoticeType>Detail Invoice</NoticeType> <Application>1</Application> </DetailBillInfo> <DetailBillInfo> <NoticeType>Detail Invoice</NoticeType> <Application>2</Application> </DetailBillInfo> <DetailBillInfo> <NoticeType>Detail Invoice</NoticeType> <Application>3</Application> </DetailBillInfo> </DetailBill>
期望输出(制表符分隔文本)
NoticeType Application Detail Invoice 1 Detail Invoice 2 Detail Invoice 3
使用的XSLT样式表
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" indent="no" /> <xsl:template match="/DetailBill"> <xsl:text>NoticeType	Application
</xsl:text> <xsl:for-each select="DetailBillInfo"> <xsl:value-of select="normalize-space(NoticeType)" /> <xsl:text>	</xsl:text> <xsl:value-of select="normalize-space(Application)" /> <xsl:text>
</xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet>
.NET 8.0 + SaxonCS 12.4 原调用代码
System.Xml.Linq.XElement xml = System.Xml.Linq.XElement.Parse("{xml}"); System.Xml.Linq.XElement stylesheet = System.Xml.Linq.XElement.Parse("{xslt}"); Saxon.Api.Processor processor = new(true); Saxon.Api.XsltCompiler comp = processor.NewXsltCompiler(); List<Saxon.Api.Error> errs = []; comp.ErrorReporter = errs.Add; Saxon.Api.XsltExecutable exe = comp.Compile(stylesheet.CreateReader()); Saxon.Api.Xslt30Transformer xfrm = exe.Load30(); Saxon.Api.XdmValue output = xfrm.ApplyTemplates(xml.CreateReader());
错误输出结果
NoticeType Application Detail Invoice 1 Detail Invoice 2 Detail Invoice 3
问题:上述操作哪里出错了?
更新:使用Serializer解决问题
改用Saxon.Api.Serializer后输出符合预期,修正后的C#代码如下:
System.Xml.Linq.XElement xml = System.Xml.Linq.XElement.Parse("{xml}"); System.Xml.Linq.XElement stylesheet = System.Xml.Linq.XElement.Parse("{xslt}"); Saxon.Api.Processor processor = new(true); Saxon.Api.XsltCompiler comp = processor.NewXsltCompiler(); List<Saxon.Api.Error> errs = []; comp.ErrorReporter = errs.Add; Saxon.Api.XsltExecutable exe = comp.Compile(stylesheet.CreateReader()); Saxon.Api.Xslt30Transformer xfrm = exe.Load30(); Saxon.Api.Serializer ser = processor.NewSerializer(); System.Text.StringBuilder sb = new(); using System.IO.StringWriter sw = new(sb); ser.OutputWriter = sw; xfrm.ApplyTemplates(xml.CreateReader(), ser);
疑问:Serializer与直接调用output.ToString()的区别是什么?
核心区别说明:
output.ToString()的行为:
调用XdmValue.ToString()是对转换后生成的XDM文本节点集合进行默认序列化,Saxon会自动在每个文本节点之间添加换行符,导致输出出现多余空行。这种方式不遵循XSLT样式表中<xsl:output>的配置,只是简单拼接节点内容并添加默认分隔符。Serializer的行为:Serializer会严格遵循XSLT样式表中<xsl:output>的设置(比如method="text"、indent="no")处理输出,完全按照样式表定义的格式序列化转换结果,不会额外添加不必要的换行或分隔符,匹配样式表预期的输出格式。
内容的提问来源于stack exchange,提问作者JTennessen
相关产品推荐
相关产品推荐

