前缀' xsi'的命名空间尚未宣布

时间:2014-11-04 09:20:09

标签: java xml dom xpath namespaces

我是java和xml解析过程的新手,所以我被困了。我的xml是:

  <?xml version="1.0" encoding="utf-16"?>
<LauncherInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/edoc/2009/Launcher.xml" hash="d8bf41f6053ab2df28704dfcda443f9199546d3b">
  <File Name="parakstitais.edoc" Location="vieta_kur_saglabat" />
  <Action xsi:type="CreateNewSignAction">
    <FileReferences>
        <FileReference Name="Document1.doc" Address="some url" />
        <FileReference Name="Scan7.pdf" Address="some url" />
        <FileReference Name="Scan8.pdf" Address="some url" />
    </FileReferences>
  </Action>
</LauncherInfo>

我的目标是提取所有Action部分,所以它应该是:

<Action xsi:type="CreateNewSignAction">
    <FileReferences>
        <FileReference Name="Document1.doc" Address="some url" />
        <FileReference Name="Scan7.pdf" Address="some url" />
        <FileReference Name="Scan8.pdf" Address="some url" />
    </FileReferences>
  </Action>

目前我的Java代码是

public static void main(String[] args) throws ParserConfigurationException,
        MalformedURLException, SAXException, IOException,
        TransformerException, XPathExpressionException {

    String URL = "my xml URL";
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(false);

    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse(new URL(URL).openStream());

     URL namespaceURL = new URL("http://www.w3.org/2001/XMLSchema-instance");
        String namespace = "xmlns:xsi="+namespaceURL.toString();

        Element messages = doc.createElementNS(namespace, "messages");
        doc.appendChild(messages);

    XPath xPath = XPathFactory.newInstance().newXPath();


    Node result = (Node) xPath.evaluate("LauncherInfo/Action", doc,
            XPathConstants.NODE);

    System.out.println(nodeToString(result));
    System.out.println("...");
}

private static String nodeToString(Node node) throws TransformerException {
    StringWriter buf = new StringWriter();
    Transformer xform = TransformerFactory.newInstance().newTransformer();
    xform.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    xform.transform(new DOMSource(node), new StreamResult(buf));
    return (buf.toString());
}

出现启动错误时: 错误:'前缀'xsi'的命名空间尚未声明。'。 我想应该做一些名称空间声明的事情。有没有办法在xpath查询中声明名称空间URI,还是有更好的解决方案?

3 个答案:

答案 0 :(得分:1)

需要提到xsi的架构位置.. 例如     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">     

答案 1 :(得分:0)

改变这个:

    URL namespaceURL = new URL("http://www.w3.org/2001/XMLSchema-instance");
    String namespace = "xmlns:xsi="+namespaceURL.toString();

    Element messages = doc.createElementNS(namespace, "messages");

要:

    String namespaceURL = "http://www.w3.org/2001/XMLSchema-instance";
    Element messages = doc.createElementNS(namespaceURL, "messages");

原因:

  1. 名称空间URI不一定是URL;将它包装在Java中的URL实例中并且可能并不总是有效的,这样做太过分了。只需使用String来保存它。
  2. 方法createElementNS期望命名空间URI按原样;它并不期望在它前面发出xmlns:xi=声明。当您将DOM树写入文件或字符串时,XML序列化程序将自动生成该声明。

答案 2 :(得分:0)

如果你想要提取所有Action部分,你应该使用像这样的解析器

string input = xmlFile;
string[] parts2 = Regex.Split(input, "(<action)|(</action>"));

你会在每个元素中获得一系列蜇伤动作代码。