java - 如何在 XPath 中使用变量?

标签 java xml xpath

我正在使用 Xpath 和 Java。

XML 有大量的OBJECT_TYPES,并且每个对象类型都有属性和参数。 每个属性和参数都有元素。

如何从 XML 文件执行以下操作。 我想知道如何使用 XPATH 字符串表达式选择所有属性元素,具体取决于 OBJECT_TYPE 字符串的名称。对象类型字符串名称取决于用户从列表中选择的名称。

我怎样才能做到这一点?

应该是这样的:

String expression = "/getObjType()/prop/*"; 

但是 getObjectType 是一种方法,因此我无法在字符串表达式中使用它。

XML 看起来像这样:

<type>
  <OBJECT_TYPE>SiteData</OBJECT_TYPE> 
  <prop>
    <DESCRIPTION>Site parameters</DESCRIPTION> 
    <PARENT>NULL</PARENT> 
    <VIRTUAL>0</VIRTUAL> 
    <VISIBLE>1</VISIBLE> 
    <PICTURE>NULL</PICTURE> 
    <HELP>10008</HELP> 
    <MIN_NO>1</MIN_NO> 
    <MAX_NO>1</MAX_NO> 
    <NAME_FORMAT>NULL</NAME_FORMAT> 
  </prop>
  <param>
    <PARAMETER>blabla</PARAMETER> 
    <DATA_TYPE>INTEGER</DATA_TYPE> 
    <DESCRIPTION>blaba</DESCRIPTION> 
    <MIN_NO>1</MIN_NO> 
    <MAX_NO>1</MAX_NO> 
    <ORDER1>1</ORDER1> 
    <NESTED>0</NESTED> 
    <DEFAULT1>NULL</DEFAULT1> 
    <FORMAT>0:16382</FORMAT> 
  </param>
  <OBJECT_TYPE>Data</OBJECT_TYPE> 
  <prop>
    <DESCRIPTION>Site parameters</DESCRIPTION> 
    <PARENT>NULL</PARENT> 
    <VIRTUAL>0</VIRTUAL> 
    <VISIBLE>1</VISIBLE> 
    <PICTURE>NULL</PICTURE> 
    <HELP>10008</HELP> 
    <MIN_NO>1</MIN_NO> 
    <MAX_NO>1</MAX_NO> 
    <NAME_FORMAT>NULL</NAME_FORMAT> 
  </prop>
  <param>
    <PARAMETER>gmgm</PARAMETER> 
    <DATA_TYPE>INTEGER</DATA_TYPE> 
    <DESCRIPTION>babla</DESCRIPTION> 
    <MIN_NO>1</MIN_NO> 
    <MAX_NO>1</MAX_NO> 
    <ORDER1>1</ORDER1> 
    <NESTED>0</NESTED> 
    <DEFAULT1>NULL</DEFAULT1> 
    <FORMAT>0:16382</FORMAT> 
  </param>
</type>

因此,根据 Object_type 的名称,我想要获取这些属性,并且我列出了 122 个对象类型,因此我必须使用一个变量来选择用户选择的类型。

 public class PropXMLParsing {

    static PropXMLParsing instance = null;

    private List<String> list = new ArrayList<String>();
    ObjType obj = new ObjType();

    public static PropXMLParsing getInstance() {

        if (instance == null) {

            instance = new PropXMLParsing();
            try {
                instance.ParserForObjectTypes();
            } catch (SAXException e) {

                e.printStackTrace();
            } catch (IOException e) {

                e.printStackTrace();
            } catch (ParserConfigurationException e) {

                e.printStackTrace();
            }

        }

        return instance;

    }

    public void ParserForObjectTypes() throws SAXException, IOException,
            ParserConfigurationException {

        try {
            FileInputStream file = new FileInputStream(new File(
                    "xmlFiles/CoreDatamodel.xml"));

            DocumentBuilderFactory builderFactory = DocumentBuilderFactory
                    .newInstance();

            builderFactory.setNamespaceAware(true);
            DocumentBuilder builder = builderFactory.newDocumentBuilder();

            Document xmlDocument = builder.parse(file);

            XPath xp = XPathFactory.newInstance().newXPath();
            final Map<String, Object> vars = new HashMap<String, Object>();
            xp.setXPathVariableResolver(new XPathVariableResolver() {
                public Object resolveVariable(QName name) {
                    return vars.get(name.getLocalPart());
                }
            });

            XPathExpression expr = xp
                    .compile("/type/OBJECT_TYPE[. = $type]/following-sibling::prop[1]");

            vars.put("type", obj.getObjectType());
            NodeList objectProps = (NodeList) expr.evaluate(xmlDocument,
                    XPathConstants.NODESET);
            System.out.println(objectProps);

            for (int i = 0; i < objectProps.getLength(); i++) {

                System.out.println(objectProps.item(i).getFirstChild()
                        .getNodeValue());
                list.add(objectProps.item(i).getFirstChild().getNodeValue());

            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
    }

    public String convertListToString() {

        StringBuilder sb = new StringBuilder();
        if (list.size() > 0) {
            sb.append(list.get(0));
            for (int i = 1; i < list.size(); i++) {
                sb.append(list.get(i));
            }
        }
        return sb.toString();
    }

}

我尝试过的第二个解决方案既不起作用也不在控制台中打印出任何内容。

public void ParserForObjectTypes() throws SAXException, IOException,
            ParserConfigurationException {

        try {
            FileInputStream file = new FileInputStream(new File(
                    "xmlFiles/CoreDatamodel.xml"));

            DocumentBuilderFactory builderFactory = DocumentBuilderFactory
                    .newInstance();

            DocumentBuilder builder = builderFactory.newDocumentBuilder();

            Document xmlDocument = builder.parse(file);

            XPath xPath = XPathFactory.newInstance().newXPath();
            NodeList nodeList = (NodeList) xPath.compile(
                    "//OBJECT_TYPE[text() = '" + obj.getObjectType()
                            + "']/following-sibling::prop[1]/*").evaluate(
                    xmlDocument, XPathConstants.NODESET);

            for (int i = 0; i < nodeList.getLength(); i++) {
                System.out.println(nodeList.item(i).getNodeName() + " = "
                        + nodeList.item(i).getTextContent());
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
    }

最佳答案

如果您想提取属于特定OBJECT_TYPEprop,您可以使用

/type/OBJECT_TYPE[. = 'some type']/following-sibling::prop[1]

在 Java 中,您可以使用字符串连接动态构建此 XPath 表达式,但如果您使用的库可以支持它,那么使用 XPath 变量会更安全(您没有在问题中说明您使用哪个库)重新使用)。例如使用 javax.xml.xpath

XPath xp = XPathFactory.newInstance().newXPath();
final Map<String, Object> vars = new HashMap<String, Object>();
xp.setXPathVariableResolver(new XPathVariableResolver() {
  public Object resolveVariable(QName name) {
    return vars.get(name.getLocalPart());
  }
});

XPathExpression expr = xp.compile("/type/OBJECT_TYPE[. = $type]/following-sibling::prop[1]");

vars.put("type", "Data");
Node dataProps = (Node)expr.evaluate(doc, XPathConstants.NODE);

vars.put("type", "SiteData");
Node siteProps = (Node)expr.evaluate(doc, XPathConstants.NODE);

// taking the value from a variable
vars.put("type", obj.getObjectType());
Node objectProps = (Node)expr.evaluate(doc, XPathConstants.NODE);

关于java - 如何在 XPath 中使用变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21258468/

相关文章:

java - 没有 box2d 的 Libgdx 光

xml - 我可以为 DTD 中的 ELEMENT 结构引用外部 DTD 吗?

c# - XPATH 查询以从存储在 SQL Server 数据库列中的 XML 中获取数据

java - OpenGL ES 中的纹理质量差

java - swagger中spring fox health路由显示多个HTTP方法

java - 表格布局 : Text in the last column is not getting displayed completly

xml - apply-template 可以与慕尼黑分组一起使用而不是 for-each 吗?

java - JAXB - 如果为 false,则抑制 boolean 属性

java - 如果使用 selenium 未找到则跳过表

xpath - 使用 XPath 连接所有子节点