如何在XPath中使用变量?

时间:2014-01-21 12:41:16

标签: 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的名称,我想得到thoose属性,我列出了122个对象类型,所以我必须使用varible来选择用户选择的那个。

 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();
    }

}

第二个解决方案我已经尝试过,aint既不会在控制台中打印任何内容。

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();
        }
    }

2 个答案:

答案 0 :(得分:2)

如果您要提取属于特定prop的{​​{1}},您可以使用

OBJECT_TYPE

在Java中,您可以使用字符串连接动态构建此XPath表达式,但如果您使用的库可以支持,那么使用XPath变量会更安全(您不会在问题中说明您的库是什么)重新使用)。例如/type/OBJECT_TYPE[. = 'some type']/following-sibling::prop[1]

javax.xml.xpath

答案 1 :(得分:1)

此XPATH将选择prop元素中OBJECT_TYPE元素内的所有元素,文本为SiteData

//OBJECT_TYPE[text() = 'SiteData']/following-sibling::prop[1]/*

要更改正在选择的OBJECT_TYPE,只需在代码中构建XPATH:

String xpath = "//OBJECT_TYPE[text() = '" + getObjType() + "']/following-sibling::prop[1]/*"

这导致代码如下:

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

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

考虑到问题中的XML以及getObjType()何时返回SiteData打印:

DESCRIPTION = Site parameters
PARENT = NULL
VIRTUAL = 0
VISIBLE = 1
PICTURE = NULL
HELP = 10008
MIN_NO = 1
MAX_NO = 1
NAME_FORMAT = NULL