看起来这在 XSLT 中是不可能的——因为缺少命名空间声明,您必须使用非命名空间感知解析器来解析 XML 文件,但我尝试过的所有 XSLT 处理器都没有对于此类文档,它们必须依赖一些仅在启用命名空间感知的情况下才存在的信息,即使相关文档实际上不包含任何命名空间节点。
因此,您必须以不同的方式处理它,例如通过自己遍历 DOM 树。既然您说您正在使用 Java,这里有一个使用 Java DOM API 的示例(该示例在Groovy控制台中按原样运行,或者将其包装在适当的类定义中并添加任何异常处理以将其作为 Java 运行)
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.w3c.dom.ls.*;
public void stripNils(Node n) {
if(n instanceof Element &&
"true".equals(((Element)n).getAttribute("xsi:nil"))) {
// element is xsi:nil - strip it out
n.getParentNode().removeChild(n);
} else {
// we're keeping this node, process its children (if any) recursively
NodeList children = n.getChildNodes();
for(int i = 0; i < children.getLength(); i++) {
stripNils(children.item(i));
}
}
}
// load the document (NB DBF is non-namespace-aware by default)
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document xmlDoc = db.parse(new File("input.xml"));
stripNils(xmlDoc);
// write out the modified document, in this example to stdout
LSSerializer ser =
((DOMImplementationLS)xmlDoc.getImplementation()).createLSSerializer();
LSOutput out =
((DOMImplementationLS)xmlDoc.getImplementation()).createLSOutput();
out.setByteStream(System.out);
ser.write(xmlDoc, out);
在您的原始示例 XML 上,这会产生正确的结果:
<?xml version="1.0" encoding="UTF-8"?>
<p849:retrieveAllValues xmlns:p849="http://package.de.bc.a">
<retrieveAllValues>
<existingValues>
<Values>
<value1> 10.00</value1>
<value2>123456</value2>
<value3>1234</value3>
<value5/>
</Values>
</existingValues>
</retrieveAllValues>
</p849:retrieveAllValues>
空行实际上并不是空的,它们包含已删除元素两侧的空白文本节点,因为此处仅删除了元素本身。