我有一个这样的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>
使用XSLT,我想将其转换为制表符分隔的文本,如下所示:
NoticeType\tApplication
Detail Invoice\t1
Detail Invoice\t2
Detail Invoice\t3
这是我使用的样式表:
<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
\t
1
Detail Invoice
\t
2
Detail Invoice
\t
3
有人能看出我做错了什么吗?
更新:
根据Martin Honnen的建议,我尝试使用
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);
一旦它跑了
sb
包含预期的输出。我对Saxon的了解不够深入,无法理解为什么要使用
Serializer
vs.只是
output.ToSting()
这会有所不同。我很高兴它能工作。