JDOM Transformer - 不要收缩空元素
JDOM Transformer - don't contract empty elements
我正在使用 JDOM 2.0.6 将 XSLT 转换为 HTML,但我遇到了以下问题 - 有时数据应该是空的,也就是说,我将在我的 XSLT 如下:
<div class="someclass"><xsl:value-of select="somevalue"/></div>
当somevalue
为空时,我得到的输出是:
<div class="someclass"/>
可能完全有效 XML,但 无效 HTML,并且在显示结果页面时会导致问题。
<span>
或 <script>
标签会出现类似的问题。
所以我的问题是 - 我如何告诉 JDOM 不要收缩空元素,并将它们保留为 <div></div>
?
编辑
我怀疑问题不在实际的 XSLTTransformer
中,而是后来使用 JDOM 写入 html 时的问题。这是我使用的代码:
XMLOutputter htmlout = new XMLOutputter(Format.getPrettyFormat());
htmlout.getFormat().setEncoding("UTF-8");
Document htmlDoc = transformer.transform(model);
htmlDoc.setDocType(new DocType("html"));
try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(outHtml), "UTF-8")) {
htmlout.output(htmlDoc, osw);
}
目前建议的添加零宽度 space 的解决方案对我有用,但我想知道是否有办法告诉 JDOM 将文档视为 HTML (无论是在转换阶段还是输出阶段,但我猜问题出在输出阶段)。
在您的例子中,XML 转换直接发生在 file/stream 上,它不再受 JDOM 控制。
在 JDOM 中,您可以selectJDOM 文档的输出是扩展的,还是空元素的未扩展输出。通常,人们从 JDOM 得到如下输出:
XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat());
xout.output(document, System.out);
不过,您可以修改输出格式,expand the empty elements
Format expanded = Format.getPrettyFormat().setExpandEmptyElements(true);
XMLOutputter xout = new XMLOutputter(expanded);
xout.output(document, System.out);
如果您 'recover'(假设它是有效的 XHTML?)XSLT 转换 xml 作为新的 JDOM 文档,您可以输出带有扩展空元素的结果。
您可以在元素之间使用 zero-width-space。这不会影响 HTML 输出,但会保持打开-关闭标签分开,因为它们具有非空内容。
<div class="someclass">​<xsl:value-of select="somevalue"/></div>
缺点是:标签不再是空的。如果您的输出是 XML,那将很重要。但是对于 HTML - 这可能是处理的最后阶段 - 应该无关紧要。
如果要转换为 HTML 文件,请考虑将 Jaxp Transformer
与 JDOMSource
和 StreamResult
一起使用,然后转换器将序列化转换结果为 HTML 如果输出方法是 html
(在您的代码中设置或使用名为 html
.
的无命名空间根元素完成
除了 "expandEmptyElements" 选项之外,您还可以创建自己的编写器并将其传递给 XMLOutputter:
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat().setExpandEmptyElements(true));
StringWriter writer = new HTML5Writer();
outputter.output(document, writer);
System.out.println(writer.toString());
此作者随后可以修改所有 HTML5 个无效元素。例如 "script" 这样的元素不会被触及:
private static class HTML5Writer extends StringWriter {
private static String[] VOIDELEMENTS = new String[] { "area", "base", "br", "col", "command", "embed", "hr",
"img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr" };
private boolean inVoidTag;
private StringBuffer voidTagBuffer;
public void write(String str) {
if (voidTagBuffer != null) {
if (str.equals("></")) {
voidTagBuffer.append(" />");
super.write(voidTagBuffer.toString());
voidTagBuffer = null;
} else {
voidTagBuffer.append(str);
}
} else if (inVoidTag) {
if (str.equals(">")) {
inVoidTag = false;
}
} else {
for (int i = 0; i < VOIDELEMENTS.length; i++) {
if (str.equals(VOIDELEMENTS[i])) {
inVoidTag = true;
voidTagBuffer = new StringBuffer(str);
return;
}
}
super.write(str);
}
}
}
我知道,这很脏,但我遇到了同样的问题,但没有找到任何其他方法。
我正在使用 JDOM 2.0.6 将 XSLT 转换为 HTML,但我遇到了以下问题 - 有时数据应该是空的,也就是说,我将在我的 XSLT 如下:
<div class="someclass"><xsl:value-of select="somevalue"/></div>
当somevalue
为空时,我得到的输出是:
<div class="someclass"/>
可能完全有效 XML,但 无效 HTML,并且在显示结果页面时会导致问题。
<span>
或 <script>
标签会出现类似的问题。
所以我的问题是 - 我如何告诉 JDOM 不要收缩空元素,并将它们保留为 <div></div>
?
编辑
我怀疑问题不在实际的 XSLTTransformer
中,而是后来使用 JDOM 写入 html 时的问题。这是我使用的代码:
XMLOutputter htmlout = new XMLOutputter(Format.getPrettyFormat());
htmlout.getFormat().setEncoding("UTF-8");
Document htmlDoc = transformer.transform(model);
htmlDoc.setDocType(new DocType("html"));
try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(outHtml), "UTF-8")) {
htmlout.output(htmlDoc, osw);
}
目前建议的添加零宽度 space 的解决方案对我有用,但我想知道是否有办法告诉 JDOM 将文档视为 HTML (无论是在转换阶段还是输出阶段,但我猜问题出在输出阶段)。
在您的例子中,XML 转换直接发生在 file/stream 上,它不再受 JDOM 控制。
在 JDOM 中,您可以selectJDOM 文档的输出是扩展的,还是空元素的未扩展输出。通常,人们从 JDOM 得到如下输出:
XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat());
xout.output(document, System.out);
不过,您可以修改输出格式,expand the empty elements
Format expanded = Format.getPrettyFormat().setExpandEmptyElements(true);
XMLOutputter xout = new XMLOutputter(expanded);
xout.output(document, System.out);
如果您 'recover'(假设它是有效的 XHTML?)XSLT 转换 xml 作为新的 JDOM 文档,您可以输出带有扩展空元素的结果。
您可以在元素之间使用 zero-width-space。这不会影响 HTML 输出,但会保持打开-关闭标签分开,因为它们具有非空内容。
<div class="someclass">​<xsl:value-of select="somevalue"/></div>
缺点是:标签不再是空的。如果您的输出是 XML,那将很重要。但是对于 HTML - 这可能是处理的最后阶段 - 应该无关紧要。
如果要转换为 HTML 文件,请考虑将 Jaxp Transformer
与 JDOMSource
和 StreamResult
一起使用,然后转换器将序列化转换结果为 HTML 如果输出方法是 html
(在您的代码中设置或使用名为 html
.
除了 "expandEmptyElements" 选项之外,您还可以创建自己的编写器并将其传递给 XMLOutputter:
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat().setExpandEmptyElements(true));
StringWriter writer = new HTML5Writer();
outputter.output(document, writer);
System.out.println(writer.toString());
此作者随后可以修改所有 HTML5 个无效元素。例如 "script" 这样的元素不会被触及:
private static class HTML5Writer extends StringWriter {
private static String[] VOIDELEMENTS = new String[] { "area", "base", "br", "col", "command", "embed", "hr",
"img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr" };
private boolean inVoidTag;
private StringBuffer voidTagBuffer;
public void write(String str) {
if (voidTagBuffer != null) {
if (str.equals("></")) {
voidTagBuffer.append(" />");
super.write(voidTagBuffer.toString());
voidTagBuffer = null;
} else {
voidTagBuffer.append(str);
}
} else if (inVoidTag) {
if (str.equals(">")) {
inVoidTag = false;
}
} else {
for (int i = 0; i < VOIDELEMENTS.length; i++) {
if (str.equals(VOIDELEMENTS[i])) {
inVoidTag = true;
voidTagBuffer = new StringBuffer(str);
return;
}
}
super.write(str);
}
}
}
我知道,这很脏,但我遇到了同样的问题,但没有找到任何其他方法。