【问题标题】:XML Namespace is getting issues for parsing the file in XPath + javaXML 命名空间在 XPath + java 中解析文件时遇到问题
【发布时间】:2012-02-06 16:53:58
【问题描述】:

我也有一个 XML

<?xml version="1.0" encoding="UTF-8"?>
<QDTM_IN300301QD ITSVersion="XML_1.0" xmlns="urn:hl7-org:v3"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:hl7-org:v3 QDTM_IN300401QD.xsd ">

    <controlActEvent classCode="CACT" moodCode="EVN">
        <code code="QDTM_TE300401QD">
        </code>
        <statusCode code="Active" />
        <subject contextConductionInd="true" contextControlCode="ON"
            typeCode="SUBJ">
            <registrationEvent classCode="REG" moodCode="EVN">
                <statusCode code="token" />
                <subject contextControlCode="AN" typeCode="SBJ">
                    <testCodeIdentifier classCode="ROL">
                        <playingTestCodeDetails classCode="ENT"
                            determinerCode="INSTANCE">
                            <code code="6399Z" codeSystemName="QTIM" codeSystemVersion="Updated">
                                <originalText><![CDATA[CBC (includes Differential and Platelets)]]></originalText>
                                <translation codeSystemName="DOSCATALOGNAMEHTMLENABLED">
                                    <originalText><![CDATA[CBC (includes Differential and Platelets)]]></originalText>
                                </translation>
                            </code>
                        </playingTestCodeDetails>
                    </testCodeIdentifier>
                </subject>
            </registrationEvent>
        </subject>
    </controlActEvent>
</QDTM_IN300301QD>

JAVA 代码:

package com.parse;

import java.io.IOException;
import java.util.Iterator;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;


public class ParseXPath {

    public String parseXML(String fileName) {
            fileName = "D://projects//Draft.xml";
            DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
            domFactory.setNamespaceAware(true); 
            DocumentBuilder builder;
            Document doc;
            try {

                builder = domFactory.newDocumentBuilder();
                doc = builder.parse(fileName);
                XPath xpath = XPathFactory.newInstance().newXPath();
                xpath.setNamespaceContext(new NamespaceContext(){public String getNamespaceURI(String prefix) {
                    return "urn:hl7-org:v3";
                }

                public String getPrefix(String namespaceURI) {
                    return null; // we are not using this.
                }

                public Iterator getPrefixes(String namespaceURI) {
                    return null; // we are not using this.
                }
                });

                String expr="//QDTM_IN300401QD/controlActEvent/subject/registrationEvent/subject/testCodeIdentifier/playingTestCodeDetails/code/translation[@codeSystemName='DOSCATALOGNAMEHTMLENABLED']/originalText/text()";

                String result = xpath.evaluate(expr, doc);
                System.out.println("Result -->  "+result); 
                return result;
            } catch (ParserConfigurationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            catch (SAXException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (XPathExpressionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return fileName;




         public static void main(String[] args) 
     throws ParserConfigurationException, SAXException, 
      IOException, XPathExpressionException {
         ParseBUXpath p = new ParseBUXpath();
         p.parseRelatedTestXML("test");



      }

}

我在 XML 中的命名空间中遇到了这个问题。当 xml 具有“xmlns="urn:hl7-org:v3" 时,xpath 查询不会让我得到数据。为了抑制我已经在 java 中编写了代码并从 XML 中删除了该行。

我需要在不从 XML 中删除命名空间部分的情况下解析 XML 并获取数据。这是与 xsd 相关的问题还是没有提到 xsd?

【问题讨论】:

  • 如果我错了“您想在解析 XML 文档时获取名称空间”,请纠正我对吗?
  • 我需要使用 XPath 表达式从 XML 获取数据,并且 XML 中的命名空间阻止它获取数据....为什么要这样做.. 为了抑制我已经删除了行XML 和 Java 代码中添加的代码。
  • 我刚刚进行了以下行更改,它对我有用..: domFactory.setNamespaceAware(false);// 将其设为真假 如果我遇到错误的方面,请纠正我.. .
  • @GOK - 这通常是错误的方向。命名空间很重要。看我的回答。

标签: java xml parsing xpath namespaces


【解决方案1】:

getNamespaceURINamespaceContext 内部的目的是将源文档中的每个命名空间与唯一的前缀相关联,以便 XPath 引擎在遇到 XPath 中的前缀字符串时知道元素属于哪个命名空间表达。这里的前缀不需要匹配源 XML 中相同 URI 的前缀(如果有);它只需要提供从前缀到正确命名空间的映射。

所以,如果你要这样写表达式:

//p:QDTM_IN300301QD/p:controlActEvent/p:subject/p:registrationEvent/p:subject
    /p:testCodeIdentifier/p:playingTestCodeDetails/p:code
        /p:translation[@codeSystemName='DOSCATALOGNAMEHTMLENABLED']
            /p:originalText/text()"

...那么你会像这样写对应的getNamespaceURI

public String getNamespaceURI(String prefix) {
    if ("p".equals(prefix)) {
        return "urn:hl7-org:v3";
    } 
    return null;
}

这就是引擎在遇到p 前缀时知道在urn:hl7-org:v3 命名空间中查找元素的方式,这就是重点。否则,引擎如何知道您不希望在 no 命名空间中有一些名为 QDTM_IN300301QD 的元素?还是其他命名空间中具有该名称的元素?

注意前缀名称是任意的;它可以是你想要的任何东西,只要它是独一无二的。也就是说,如果您的文档中有其他命名空间,那么您需要修改 getNamespaceURI 以了解这些命名空间并为每个命名空间分配一个唯一的前缀。

这是一个完整的(最小的)示例:

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true); 
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("Draft.xml");
XPath xpath = XPathFactory.newInstance().newXPath();
NamespaceContext ctx = new NamespaceContext() {
    public String getNamespaceURI(String prefix) {
        if ("p".equals(prefix)) {
            return "urn:hl7-org:v3";
        } 
        return null;
    }
    public String getPrefix(String uri) {
        throw new UnsupportedOperationException();
    }
    public Iterator getPrefixes(String uri) {
        throw new UnsupportedOperationException();
    }
};
xpath.setNamespaceContext(ctx);
XPathExpression expr = xpath.compile("//p:QDTM_IN300301QD/p:controlActEvent" +
        "/p:subject/p:registrationEvent" + 
        "/p:subject/p:testCodeIdentifier/p:playingTestCodeDetails/p:code" +
        "/p:translation[@codeSystemName='DOSCATALOGNAMEHTMLENABLED']" +
        "/p:originalText/text()");      
System.out.println("[" + expr.evaluate(doc, XPathConstants.STRING));

【讨论】:

    【解决方案2】:

    您需要在表达式中包含命名空间,命名空间可以替换为“前缀”,作为对完整命名空间 uri 的查找。

    String expr="//prefix:QDTM_IN300401QD/controlActEvent/...."
    

    您使用命名空间映射设置,看看https://www.ibm.com/developerworks/library/x-javaxpathapi/index.htmlhttps://xml.apache.org/xalan-j/xpath_apis.html#namespacecontext

    如果 xml 仅包含一个命名空间,您也可以尝试在表达式中使用 //*:elementname 来简单地忽略元素名称存在于哪个命名空间中。

    查看http://www.w3schools.com/XML/xml_namespaces.asp 以了解命名空间的使用方式以及它们解决的问题

    【讨论】:

    • 我不明白这个;就像是说我们可以用来创建我们的 NameSpaceContext 但我可以有许多表达式所以我需要创建 NameSpaceContext 并在我的表达式中添加 pre: ???
    • 您需要做的是创建一个 NameSpaceContext 包含所有可能的命名空间的查找。在您的示例中,有一个默认命名空间 xmlns="urn:hl7-org:v3" 和一个额外的 xmlns:xsi,它在实际的 xml 内容中从未使用过。在评估您的表达式时,它会查找以“:”结尾的任何内容,如果找到任何内容,它会调用 getNamespaceURI(String prefix) 以找出完整的 Uri,//pre:QDTM_IN.... 前缀变量变为“pre”,完整的 uri 被扩展并继续评估。默认命名空间隐式导致所有元素都以它为前缀。
    • +1 - 这就是问题所在。我提供额外答案的唯一原因是似乎仍然存在一些混乱。
    猜你喜欢
    • 2016-05-14
    • 2011-02-18
    • 2014-02-06
    • 2023-03-26
    • 2023-04-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 2014-09-16
    相关资源
    最近更新 更多