Xpath仅选择空值为

时间:2015-04-30 13:14:14

标签: java xml xpath

如何格式化此表达式,以便在运行for循环时,仅选择分析属性为空的位置。原因是有多个具有相同值的templateNames。这是我的尝试,但无法开始工作

String theXpath = "//report-plan[@name='"+ templateName +"']/settings/@analysis=''";

示例代码:

public class XPathTestReports {
    public static void main(String[] args) {
        try {
            String outputFile = "c:/workspace/samplenew.xml";
            String inputFile = "c:/workspace/sample.xml";

            Document doc = DocumentBuilderFactory.newInstance()
            .newDocumentBuilder().parse(new InputSource(inputFile));

            // locate the node(s)
            XPath xpath = XPathFactory.newInstance().newXPath();

            // lOAD THE File
            CSVImporterReports loader = new CSVImporterReports("C:/REPORT_TEMPLATES.csv");
            List < OnConfig > entries = loader.getEntries();

            for (OnConfig c: entries) {
                String templateName = c.getTemplateName();
                String analName = c.getAnalysisName();
                String paramName = c.getParamName();
                String theXpath = "//report-plan[@name='" + templateName + "']/settings/@analysis=''";
                NodeList nodes = (NodeList) xpath.evaluate(theXpath, doc, XPathConstants.NODESET);

                // make the change
                for (int i = 0; i < nodes.getLength(); i++) {
                    nodes.item(i).setTextContent(analName);
                    // nodes.item(i).setTextContent(paramName);
                }
            }

            try {
                // save the result
                Transformer xformer = TransformerFactory.newInstance().newTransformer();
                xformer.transform(new DOMSource(doc), new StreamResult(new File(outputFile)));
            } catch (TransformerConfigurationException e) {
                // TODO Auto-generated catch block
            } catch (TransformerFactoryConfigurationError e) {
                // TODO Auto-generated catch block
            } catch (TransformerException e) {
                // TODO Auto-generated catch block
            }
        } 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();
        }
    }
}

示例XML:

<report-plan name="generic">
              <columns>
                <column name="Nominal" subtotal-function="Sum" total-function="Sum"/>
                <column name="Trade"/>
              </columns>
              <settings analysis="" analysisParameters="" filtering-enabled="true" object-actions="false" show-object-actions="true" sorting-enabled="true"/>
</report-plan>
<report-plan name="generic">
              <columns>
                <column name="Nominal" subtotal-function="Sum" total-function="Sum"/>
                <column name="Trade"/>
              </columns>
              <settings analysis="" analysisParameters="" filtering-enabled="true" object-actions="false" show-object-actions="true" sorting-enabled="true"/>
</report-plan>
<report-plan name="sensitive">
              <columns>
                <column name="Nominal" subtotal-function="Sum" total-function="Sum"/>
                <column name="Trade"/>
              </columns>
              <settings analysis="" analysisParameters="" filtering-enabled="true" object-actions="false" show-object-actions="true" sorting-enabled="true"/>
</report-plan>

目前,我的代码为两个名为generic的报告输入了相同的值。即使分析属性具有要输入的不同值。即使报告名称相同,我也需要输入不同分析值的代码。

输出:

<report-plan name="generic">
              <columns>
                <column name="Nominal" subtotal-function="Sum" total-function="Sum"/>
                <column name="Trade"/>
              </columns>
              <settings analysis="newValue" analysisParameters="" filtering-enabled="true" object-actions="false" show-object-actions="true" sorting-enabled="true"/>
</report-plan>
<report-plan name="generic">
              <columns>
                <column name="Nominal" subtotal-function="Sum" total-function="Sum"/>
                <column name="Trade"/>
              </columns>
              <settings analysis="newValue" analysisParameters="" filtering-enabled="true" object-actions="false" show-object-actions="true" sorting-enabled="true"/>
</report-plan>
<report-plan name="sensitive">
              <columns>
                <column name="Nominal" subtotal-function="Sum" total-function="Sum"/>
                <column name="Trade"/>
              </columns>
              <settings analysis="someValue" analysisParameters="" filtering-enabled="true" object-actions="false" show-object-actions="true" sorting-enabled="true"/>
</report-plan>

CSV样本

TEMPLATE_NAME   ANALYSIS_NAME   PARAM_NAME
generic         analval1        paramval1
generic         analval2        paramval2
sensitivity     analval3        paramval3

2 个答案:

答案 0 :(得分:3)

好的,我想我知道你在这里会发生什么。您希望使用XPath为您提供存在且为空的@analysis节点,以便您可以使用某些已配置的值填充它们。

String theXpath = "//report-plan[@name='" + templateName + "']/settings/@analysis[.='']";

编辑添加:

现在,请记住,这将为模板名称选择所有@analysis节点。当您执行第二级for循环时,您正在更改所有这些循环。在下一个名为“generic”的CSV上,它将找不到要更改的节点。

替换:

for (int i = 0; i < nodes.getLength(); i++) {
    nodes.item(i).setTextContent(analName);
}

使用:

if (nodes.getLength() > 0) {
    nodes.item(0).setTextContent(analName);
}

答案 1 :(得分:1)

也许你的意思是

String theXpath = "//report-plan[@name='"+ templateName +"' and not(settings/@analysis > '')]";

这将选择具有特定名称但不包含<report-plan>(或空名称)的所有settings/@analysis元素。