3

我有以下 xml,其中包含几个带有 xsi:nil="true" 的 xml 标签。这些是基本上为空的标签。我无法使用/找到任何 sxlt 转换器来从 xml 中删除这些标签并获取 xml 的其余部分。

<?xml version="1.0" encoding="utf-8"?>
<p849:retrieveAllValues xmlns:p849="http://package.de.bc.a">
    <retrieveAllValues>
        <messages xsi:nil="true" />
        <existingValues>
            <Values>
                <value1> 10.00</value1>
                <value2>123456</value2>
                <value3>1234</value3>
                <value4 xsi:nil="true" />
                <value5 />
            </Values>
        </existingValues>
        <otherValues xsi:nil="true" />
        <recValues xsi:nil="true" />
    </retrieveAllValues>
</p849:retrieveAllValues>
4

2 回答 2

4

你得到的错误原因

[致命错误] file2.xml:5:30:与元素类型“messages”关联的属性“xsi:nil”的前缀“xsi”未绑定。

没有声明名为“xsi”的前缀,您应该在根元素中指定它,例如:

<p849:retrieveAllValues xmlns:p849="http://package.de.bc.a"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retrieveAllValues>
    <messages xsi:nil="true" />
       // other code...

更新

如果您无法更改从 web 服务接收到的 xml 文档,您可以尝试下一种方法(如果您可以接受这种方法):

  1. 更改您的xslt文档以处理 xml 文档而不指定元素前缀
  2. 将 的属性设置namespaceAwareDocumentBuilderFactoryfalse

在这之后你的变压器不应该抱怨

于 2013-02-13T19:21:42.587 回答
1

看起来这在 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>

空行实际上并不是空的,它们包含已删除元素两侧的空白文本节点,因为此处仅删除了元素本身。

于 2013-02-14T15:12:27.017 回答