XRechnung Visualizer 和 Saxon-HE for .NET 自闭 DIV 标签的问题
Problem with self-closing DIV tags with XRechnung Visualizer and Saxon-HE for .NET
我想通过使用 itplr-kosit's xrechnung-visualization, to transform XRechnung to HTML. As processor I use Saxonica's Saxon-HE 实现带有 .NET/C# 的 XRechnung 可视化工具。现在我正在努力处理无效 HTML 作为自动关闭 DIV 形式的输出。
转换代码如下:
public static string TransformXml(string xmlData, string xslData)
{
var xsltProcessor = new Saxon.Api.Processor();
var documentBuilder = xsltProcessor.NewDocumentBuilder();
documentBuilder.BaseUri = new Uri("file://");
var xdmNode = documentBuilder.Build(new StringReader(xmlData));
var xsltCompiler = xsltProcessor.NewXsltCompiler();
var xsltExecutable = xsltCompiler.Compile(new StringReader(xslData));
var xsltTransformer = xsltExecutable.Load();
xsltTransformer.InitialContextNode = xdmNode;
var results = new Saxon.Api.XdmDestination();
xsltTransformer.Run(results);
return results.XdmNode.OuterXml;
}
来电:
var xmlData = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "xrechnung.xml"));
var xslDataToXR = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "cii-xr.xsl"));
var xslDataToHTML = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "xrechnung-html.xsl"));
var xrXMLData = TransformXml(xmlData, xslDataToXR);
var htmlData = TransformXml(xrXMLData, xslDataToHTML);
File.WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "result.html"), htmlData);
有效...解决了问题,在生成的 HTML 中,所有未填充的字段都转换为 自关闭 DIV 标签.
例如,以下片段来自 xrechnung-html.xsl
...
<div class="boxzeile">
<div class="boxdaten legende">Postfach:</div>
<div id="BT-51" title="BT-51" class="boxdaten wert"><xsl:value-of select="xr:BUYER_POSTAL_ADDRESS/xr:Buyer_address_line_2"/></div>
</div>
... 将呈现如下 HTML,因为 xml 没有为 Buyer_address_line_2
提供值:
<div class="boxzeile">
<div class="boxdaten legende">Postfach:</div>
<div id="BT-51" title="BT-51" class="boxdaten wert"/>
</div>
浏览器将自闭DIV解释为打开标签,完整视图被破坏。
有什么想法吗?
如果您让 Saxon 不使用 XdmDestination 而是使用 Serializer 直接写入文件或流或字符串编写器来进行序列化,那么我相信它会遵守 HTML 序列化规则。在 XML 和 XSLT 的上下文中,我建议让 XML 解析器和 XSLT 处理器尽可能多地处理输入解析和输出序列化,而不是从文件中读取字符串或将字符串写入文件使用文件 API。
因为你似乎想链接两个转换我猜使用
var xslt1 = xsltExecutable1.Load30();
var xslt2 = xsltExecutable2.Load30();
using (var inputStream = File.OpenRead(Path.Combine(Directory.GetCurrentDirectory(), "xrechnung.xml")) {
using (var resultStream = File.OpenWrite(Path.Combine(Directory.GetCurrentDirectory(), "result.html") {
xslt1.Transform(inputStream , xslt2.AsDocumentDestination(xslt2.NewSerializer(resultStream)));
}
}
是一种可行的方法。
当然也可以直接在 XSLT 3 中更改两个样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="step1-uri" as="xs:string">https://github.com/itplr-kosit/xrechnung-visualization/raw/master/src/xsl/ubl-invoice-xr.xsl</xsl:param>
<xsl:param name="step2-uri" as="xs:string">https://github.com/itplr-kosit/xrechnung-visualization/raw/master/src/xsl/xrechnung-html.xsl</xsl:param>
<xsl:output method="html" indent="yes" html-version="5"/>
<xsl:template match="/">
<xsl:sequence
select="transform(map {
'source-node' : .,
'stylesheet-location' : $step1-uri
})?output ! transform(map {
'source-node' : .,
'stylesheet-location' : $step2-uri
})?output"/>
</xsl:template>
</xsl:stylesheet>
通常可以使用 fold-left
链接一系列样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="step1-uri" as="xs:string">https://github.com/itplr-kosit/xrechnung-visualization/raw/master/src/xsl/ubl-invoice-xr.xsl</xsl:param>
<xsl:param name="step2-uri" as="xs:string">https://github.com/itplr-kosit/xrechnung-visualization/raw/master/src/xsl/xrechnung-html.xsl</xsl:param>
<xsl:param name="xslt-locations" as="xs:string*" select="$step1-uri, $step2-uri"/>
<xsl:output method="html" indent="yes" html-version="5"/>
<xsl:template match="/">
<xsl:sequence
select="fold-left(
$xslt-locations,
.,
function($doc, $xslt-location) {
transform(map { 'source-node' : $doc, 'stylesheet-location' : $xslt-location })?output
}
)"/>
</xsl:template>
</xsl:stylesheet>
确保将结果序列化为 HTML(或 XHTML)而不是 XML。
您当前正在将结果发送到 in-memory 树,然后使用 OuterXML
属性 对其进行序列化,这为您提供了 XML 序列化。
相反,将输出发送到序列化程序,并且 select 序列化方法 HTML 使用样式表中的 <xsl:output>
,或通过设置 Serializer
对象的属性.
我想通过使用 itplr-kosit's xrechnung-visualization, to transform XRechnung to HTML. As processor I use Saxonica's Saxon-HE 实现带有 .NET/C# 的 XRechnung 可视化工具。现在我正在努力处理无效 HTML 作为自动关闭 DIV 形式的输出。
转换代码如下:
public static string TransformXml(string xmlData, string xslData)
{
var xsltProcessor = new Saxon.Api.Processor();
var documentBuilder = xsltProcessor.NewDocumentBuilder();
documentBuilder.BaseUri = new Uri("file://");
var xdmNode = documentBuilder.Build(new StringReader(xmlData));
var xsltCompiler = xsltProcessor.NewXsltCompiler();
var xsltExecutable = xsltCompiler.Compile(new StringReader(xslData));
var xsltTransformer = xsltExecutable.Load();
xsltTransformer.InitialContextNode = xdmNode;
var results = new Saxon.Api.XdmDestination();
xsltTransformer.Run(results);
return results.XdmNode.OuterXml;
}
来电:
var xmlData = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "xrechnung.xml"));
var xslDataToXR = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "cii-xr.xsl"));
var xslDataToHTML = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "xrechnung-html.xsl"));
var xrXMLData = TransformXml(xmlData, xslDataToXR);
var htmlData = TransformXml(xrXMLData, xslDataToHTML);
File.WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "result.html"), htmlData);
有效...解决了问题,在生成的 HTML 中,所有未填充的字段都转换为 自关闭 DIV 标签.
例如,以下片段来自 xrechnung-html.xsl
...
<div class="boxzeile">
<div class="boxdaten legende">Postfach:</div>
<div id="BT-51" title="BT-51" class="boxdaten wert"><xsl:value-of select="xr:BUYER_POSTAL_ADDRESS/xr:Buyer_address_line_2"/></div>
</div>
... 将呈现如下 HTML,因为 xml 没有为 Buyer_address_line_2
提供值:
<div class="boxzeile">
<div class="boxdaten legende">Postfach:</div>
<div id="BT-51" title="BT-51" class="boxdaten wert"/>
</div>
浏览器将自闭DIV解释为打开标签,完整视图被破坏。
有什么想法吗?
如果您让 Saxon 不使用 XdmDestination 而是使用 Serializer 直接写入文件或流或字符串编写器来进行序列化,那么我相信它会遵守 HTML 序列化规则。在 XML 和 XSLT 的上下文中,我建议让 XML 解析器和 XSLT 处理器尽可能多地处理输入解析和输出序列化,而不是从文件中读取字符串或将字符串写入文件使用文件 API。
因为你似乎想链接两个转换我猜使用
var xslt1 = xsltExecutable1.Load30();
var xslt2 = xsltExecutable2.Load30();
using (var inputStream = File.OpenRead(Path.Combine(Directory.GetCurrentDirectory(), "xrechnung.xml")) {
using (var resultStream = File.OpenWrite(Path.Combine(Directory.GetCurrentDirectory(), "result.html") {
xslt1.Transform(inputStream , xslt2.AsDocumentDestination(xslt2.NewSerializer(resultStream)));
}
}
是一种可行的方法。
当然也可以直接在 XSLT 3 中更改两个样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="step1-uri" as="xs:string">https://github.com/itplr-kosit/xrechnung-visualization/raw/master/src/xsl/ubl-invoice-xr.xsl</xsl:param>
<xsl:param name="step2-uri" as="xs:string">https://github.com/itplr-kosit/xrechnung-visualization/raw/master/src/xsl/xrechnung-html.xsl</xsl:param>
<xsl:output method="html" indent="yes" html-version="5"/>
<xsl:template match="/">
<xsl:sequence
select="transform(map {
'source-node' : .,
'stylesheet-location' : $step1-uri
})?output ! transform(map {
'source-node' : .,
'stylesheet-location' : $step2-uri
})?output"/>
</xsl:template>
</xsl:stylesheet>
通常可以使用 fold-left
链接一系列样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="step1-uri" as="xs:string">https://github.com/itplr-kosit/xrechnung-visualization/raw/master/src/xsl/ubl-invoice-xr.xsl</xsl:param>
<xsl:param name="step2-uri" as="xs:string">https://github.com/itplr-kosit/xrechnung-visualization/raw/master/src/xsl/xrechnung-html.xsl</xsl:param>
<xsl:param name="xslt-locations" as="xs:string*" select="$step1-uri, $step2-uri"/>
<xsl:output method="html" indent="yes" html-version="5"/>
<xsl:template match="/">
<xsl:sequence
select="fold-left(
$xslt-locations,
.,
function($doc, $xslt-location) {
transform(map { 'source-node' : $doc, 'stylesheet-location' : $xslt-location })?output
}
)"/>
</xsl:template>
</xsl:stylesheet>
确保将结果序列化为 HTML(或 XHTML)而不是 XML。
您当前正在将结果发送到 in-memory 树,然后使用 OuterXML
属性 对其进行序列化,这为您提供了 XML 序列化。
相反,将输出发送到序列化程序,并且 select 序列化方法 HTML 使用样式表中的 <xsl:output>
,或通过设置 Serializer
对象的属性.