代码之家  ›  专栏  ›  技术社区  ›  JTennessen

Saxon XSLT输出中的额外换行符

  •  0
  • JTennessen  · 技术社区  · 4 月前

    我有一个这样的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&#x9;Application&#xA;</xsl:text>
        <xsl:for-each select="DetailBillInfo">
          <xsl:value-of select="normalize-space(NoticeType)" />
          <xsl:text>&#x9;</xsl:text>
          <xsl:value-of select="normalize-space(Application)" />
          <xsl:text>&#xA;</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() 这会有所不同。我很高兴它能工作。

    1 回复  |  直到 4 月前
        1
  •  1
  •   Martin Honnen    4 月前

    如果您希望文本输出,其中Saxon根据您的 <xsl:output method="text" indent="no" /> 那么,我建议您不要使用XdmValue作为以下结果 ApplyTemplates 而是通过a Serializer (例如a StringWriter 或流)作为第二个参数 应用模板 .

    然后打电话 ToString() 在StringWriter上,我认为你会得到你想要的字符串输出,或者当然,如果你向 序列化程序 .