我正在尝试读取一个文件来生成一个DOM文档,但该文件有空格和换行符,我试图忽略它们,但我不能:
DocumentBuilderFactory docfactory=DocumentBuilderFactory.newInstance();
docfactory.setIgnoringElementContentWhitespace(true);
我在Javadoc中看到setIgnoringElementContentWhitespace方法仅在启用验证标志时才会运行,但我没有文档的DTD或XML Schema。
我该怎么办?
更新
我不喜欢介绍mySelf< !ELEMENT ...声明,我试过了 在Tomalak指出的forum中提出的解决方案,但它不起作用,我在linux环境中使用了java 1.6。我想如果不再提议,我会用一些方法来忽略空白文本节点
答案 0 :(得分:10)
'IgnoringElementContentWhitespace'不是要删除所有纯空白文本节点,只有空格在模式中描述为具有ELEMENT内容的空格节点 - 也就是说,它们只包含其他元素和从不发短信。
如果您没有使用架构(DTD或XSD),则元素内容默认为MIXED,因此此参数将永远不会产生任何影响。 (除非解析器提供非标准的DOM扩展来将所有未知元素视为包含ELEMENT内容,据我所知,Java可用的内容不是。)
您可以在进入解析器的途中破解文档以包含架构信息,例如通过向<中添加内部子集。 !DOCTYPE ... [...]>声明包含< !ELEMENT ...>声明,然后使用IgnoringElementContentWhitespace参数。
或者,可能更容易,您可以在后期处理中或在使用LSParserFilter进入时删除空白节点。
答案 1 :(得分:5)
这是一个(真的)迟到的答案,但这是我如何解决它。我编写了自己的NodeList
类实现。它只是忽略空的文本节点。代码如下:
private static class NdLst implements NodeList, Iterable<Node> {
private List<Node> nodes;
public NdLst(NodeList list) {
nodes = new ArrayList<Node>();
for (int i = 0; i < list.getLength(); i++) {
if (!isWhitespaceNode(list.item(i))) {
nodes.add(list.item(i));
}
}
}
@Override
public Node item(int index) {
return nodes.get(index);
}
@Override
public int getLength() {
return nodes.size();
}
private static boolean isWhitespaceNode(Node n) {
if (n.getNodeType() == Node.TEXT_NODE) {
String val = n.getNodeValue();
return val.trim().length() == 0;
} else {
return false;
}
}
@Override
public Iterator<Node> iterator() {
return nodes.iterator();
}
}
然后将所有NodeList
包装在此类中,它将有效地忽略所有空白节点。 (我将其定义为带有0长度修剪文本的文本节点。)
它还具有能够在for-each循环中使用的额外好处。
答案 2 :(得分:2)
我这样做是有效的
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setIgnoringElementContentWhitespace(true);
dbFactory.setSchema(schema);
dbFactory.setNamespaceAware(true);
NodeList nodeList = element.getElementsByTagNameNS("*", "associate");
答案 3 :(得分:1)
我最终遵循@bobince的使用LSParserFilter的想法。是的,该接口在https://docs.oracle.com/javase/7/docs/api/org/w3c/dom/ls/LSParserFilter.html中有文档说明,但是很难找到好的示例/说明材料。经过大量搜索之后,我找到了http://www.informit.com/articles/article.aspx?p=31297&seqNum=29上的《 DOM Level 3加载和保存XML参考指南》(Nicholas Chase,2003年3月14日)。那对我有很大帮助。这是我的代码的一部分,它与org.custommonkey.xmlunit进行XML差异。 (这是我自己的时间写的工具,可以帮助我完成有偿工作,所以在事情变慢时,我留下了很多东西,例如更好的异常处理)。
我特别喜欢使用LSParserFilter,因为出于我的目的,将来我可能还会添加一个选项来忽略id属性,这对于此框架而言应该是一个容易的增强。
// A small portion of my main class.
// Other imports may be necessary...
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSParser;
import org.w3c.dom.ls.LSParserFilter;
Document controlDoc = null;
Document testDoc = null;
try {
System.setProperty(DOMImplementationRegistry.PROPERTY, "org.apache.xerces.dom.DOMImplementationSourceImpl");
DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
LSParser builder = impl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
LSParserFilter filter = new InputFilter();
builder.setFilter(filter);
controlDoc = builder.parseURI(files[0].getPath());
testDoc = builder.parseURI(files[1].getPath());
} catch (Exception exc) {
System.out.println(exc.getMessage());
}
//--------------------------------------
import org.w3c.dom.ls.LSParserFilter;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.NodeFilter;
public class InputFilter implements LSParserFilter {
public short acceptNode(Node node) {
if (Utils.isNewline(node)) {
return NodeFilter.FILTER_REJECT;
}
return NodeFilter.FILTER_ACCEPT;
}
public int getWhatToShow() {
return NodeFilter.SHOW_ALL;
}
public short startElement(Element elem) {
return LSParserFilter.FILTER_ACCEPT;
}
}
//-------------------------------------
// From my Utils.java:
public static boolean isNewline(Node node) {
return (node.getNodeType() == Node.TEXT_NODE) && node.getTextContent().equals("\n");
}
答案 4 :(得分:0)
试试这个:
private static Document prepareXML(String param) throws ParserConfigurationException, SAXException, IOException {
param = param.replaceAll(">\\s+<", "><").trim();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource in = new InputSource(new StringReader(param));
return builder.parse(in);
}