https://bz.apache.org/bugzilla/show_bug.cgi?id=65327
Bug ID: 65327 Summary: XMLProperties Product: Ant Version: unspecified Hardware: Other OS: All Status: NEW Severity: enhancement Priority: P2 Component: Props Antlib Assignee: notifications@ant.apache.org Reporter: jfm0...@gmail.com Target Milestone: --- ===================================== File Test.java import org.apache.tools.ant.Project; import junix.ant.tasks.XmlPropsTask; public class Test { public static void main(String[] args) { XmlPropsTask t = new XmlPropsTask(); t.setFile("properties.xml"); t.setPrefix("a."); t.setExpression("/properties/a/@*"); t.setVerbose("true"); Project p = new Project(); t.setProject(p); t.execute(); } } ====================================== File XmlPropsTask.java /* * Copyright (c) 2021 Jean-Francois Martel v202105151146. All rights reserved. * This program and the accompanying materials are made available under the * terms of the MIT License which is available at * http://www.opensource.org/licenses/mit-license.php */ package junix.ant.tasks; import java.io.File; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.tools.ant.Task; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import junix.xml.XPathParser; public class XmlPropsTask extends Task { private String file; private String prefix; private String expression; private boolean verbose; HashMap<String, String> propsList = new HashMap<String, String>(); public void setVerbose(String verbose) { this.verbose = Boolean.parseBoolean(verbose); } public void setFile(String file) { this.file = file; } public void setPrefix(String prefix) { this.prefix = prefix; } public void setExpression(String expression) { this.expression = expression; } public void execute() { Hashtable<String, Object> props = getProject().getProperties(); props.forEach((k, v) -> { propsList.put(k.toString(), v.toString()); }); if(verbose) getProject().log(this.getTaskName()+" parse:"+new File(file).getAbsolutePath()); setXMLProps(); propsList.forEach((k, v) -> { getProject().setNewProperty(k.toString(), v.toString()); }); } private void setXMLProps() { final Pattern pattern = Pattern.compile("[$][{](.+?)[}]", Pattern.DOTALL); HashSet<String> replaceList = new HashSet<String>(); XPathParser xpp = new XPathParser(); Document doc = xpp.getDocument(file); NodeList nodeList = xpp.getNodeList(expression, doc); if (prefix != null) for (int i = 0; i < nodeList.getLength(); i++) { Node value = nodeList.item(i); propsList.put(prefix + value.getNodeName(), value.getNodeValue()); } propsList.forEach((k, v) -> { Matcher matcher = pattern.matcher(v.toString()); while (matcher.find()) { replaceList.add(matcher.group(1)); } }); int limit = 3; int count = 0; while (replaceList.size() != 0) { replaceVariables(pattern, replaceList, propsList); if (count > limit) break; count++; } } private void replaceVariables(final Pattern pattern, HashSet<String> replaceList, HashMap<String, String> propsList) { propsList.forEach((k, v) -> { String oldValue = v.toString(); if (oldValue.contains("${")) { Matcher matcher = pattern.matcher(v.toString()); while (matcher.find()) { String matche = matcher.group(1); String replacement = propsList.get(matche); if (replacement != null) if (!replacement.contains("${")) { String newValue = oldValue.replace("${" + matche + "}", replacement); if(verbose) { System.out.println("M:"+ matche ); System.out.println("V:"+k.toString()); System.out.println("N:"+newValue); } propsList.put(k.toString(), newValue); } } } else { replaceList.remove(k.toString()); } }); } } ========================= File XPathParser.java /* * Copyright (c) 2021 Jean-Francois Martel v202105151146. All rights reserved. * This program and the accompanying materials are made available under the * terms of the MIT License which is available at * http://www.opensource.org/licenses/mit-license.php */ package junix.xml; import static java.util.stream.Collectors.toList; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class XPathParser { public static String[] getValues(XPathParser xpathParser, Document doc, String expression, String itemName) throws XPathExpressionException { List<String> valuesList = new ArrayList<>(); NodeList nodeList = xpathParser.getNodeList(expression, doc); for (int i = 0; i < nodeList.getLength(); i++) { String value = xpathParser.getNodeValue(itemName, i, nodeList); valuesList.add(value); } return valuesList.toArray(new String[valuesList.size()]); } public Document getDocument(String fileName) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; Document doc = null; try { builder = factory.newDocumentBuilder(); doc = builder.parse(new File(fileName)); } catch (ParserConfigurationException | SAXException | IOException e) { e.printStackTrace(); } return doc; } public String[] getNode(String itemName, NodeList nodeList) throws XPathExpressionException { String[] results = new String[nodeList.getLength()]; for (int index = 0; index < nodeList.getLength(); index++) { Node node = nodeList.item(index); Node name = node.getAttributes().getNamedItem(itemName); results[index] = name.getNodeValue(); } return results; } public NodeList getNodeList(String expression, Document doc) { XPath xPath = XPathFactory.newInstance().newXPath(); NodeList nodeList = null; try { nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET); } catch (Exception e) { e.printStackTrace(); } return nodeList; } public String getNodeValue(String itemName, int index, NodeList nodeList) { Node node = nodeList.item(index); Node name = node.getAttributes().getNamedItem(itemName); if (name == null) return ""; return name.getNodeValue(); } public static List<String> getValues(String path, String expression, String itemName) throws XPathExpressionException { XPathParser xpathParser = new XPathParser(); Document doc = xpathParser.getDocument(path); return Arrays.stream(XPathParser.getValues(xpathParser, doc, expression, itemName)).map(String::valueOf) .collect(toList()); } } ============== File: build.xml <project name="test xmlprops" default="default" xmlns:if="ant:if" xmlns:unless="ant:unless" basedir="." > <taskdef name="xmlprops" classname="junix.ant.tasks.XmlPropsTask" onerror="ignore"> <classpath> <pathelement path="target/classes/"/> </classpath> </taskdef> <target name="default"> <xmlproperty file="properties.xml" keeproot="false" rootdirectory="properties" collapseattributes="true" /> <echoproperties format="text" prefix="a."/> </target> <target name="custom xml xmlproperty"> <xmlprops file="properties.xml" prefix="a." expression="/properties/a/@*" verbose="false" /> <echoproperties format="text" prefix="a." /> </target> </project> ================= File: properties.xml <?xml version="1.0" encoding="UTF-8"?> <properties><a c= "C" b= "B ${a.a}" a= "A" d= "D ${a.c}" g= "G ${a.c}" /> </properties> -- You are receiving this mail because: You are the assignee for the bug.