Search code examples
javaxmljersey

Java program to get variable name from a place holder available in a XML file


Hope you all are good. I have one requirement where I need to pick the variable name from placeholder which is available in a XML file. I have one XML file that have all placeholders and those placeholders are starting with a $ symbol. My Task is to get that placeholder and from it I need to get the variable name.

for example, If XML file have placeholder like $Variable1 then it will get Variable1 from that placeholder.

Following is the code that I am using :

public static String replaceConfigParam(String xmlFile, Object structure) {
    for (String key : getConstants(xmlFile)) {
        String actualKey = (new StringBuilder().append("$*").append(key).append("$")).toString();

        try {

            String value = BeanUtils.getProperty(structure, key);
            if (value != null) {
                xmlFile = xmlFile.replace(actualKey, value);
            }

        } catch (IllegalAccessException e) {
            logger.error("failed to get the property from  object " + e.getMessage());
        } catch (InvocationTargetException e) {
            logger.error("failed to get the property from  object" + e.getMessage());
        } catch (NoSuchMethodException e) {
            logger.error("failed to get the property from  object " + e.getMessage());
        } catch (Exception e) {
            logger.error("failed to get value from the property " + e.getMessage());
        }
    }
    return xmlFile;

Following is the getConstant method:

private static List<String> getConstants(String domainConfig) {
    String[] arr = domainConfig.split("\\$");
    List<String> paramsExtracted = new ArrayList<String>();
    for (String key : arr) {
        paramsExtracted.add(key.replace("$", ""));
                }
    return paramsExtracted;
}

following is the XML file which have $ in it and I need to extract the variable from the same file:

<tunnel>
        <units>
          <entry name="tunnel.1">
            <ip>
              <entry name="$ABC"/>
            </ip>
            <interface-management-profile>mgt</interface-management-profile>
          </entry>
        </units>
      </tunnel> 

Solution

  • I am assuming your question is:

    "How to extract the entry name property for all variables identified by a $-sign at the start".

    You can do this with regular expressions, but since you are working with XML, you may use Xpath + an xpath parser. See here:

    import java.io.IOException;
    import java.io.StringReader;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.xpath.XPathConstants;
    import javax.xml.xpath.XPathExpression;
    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.InputSource;
    import org.xml.sax.SAXException;
    
    public class ExtractVar {
    
        static String xml = "<tunnel>" +
        "<units>" +
          "<entry name=\"tunnel.1\">"+
            "<ip>"+
           "   <entry name=\"$ABC\"/>"+
          "  </ip>"+
         "   <interface-management-profile>mgt</interface-management-profile>"+
        "  </entry>"+
       " </units>"+
      "</tunnel>";
        
        
        public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
            DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document document = db.parse(new InputSource(new StringReader(xml)));
            
            XPathFactory xpathFactory = XPathFactory.newInstance();
            XPathExpression xpath = xpathFactory.newXPath().compile("//entry");
            
            NodeList entryNodes = (NodeList) xpath.evaluate(document, XPathConstants.NODESET);
            for(int i =0; i<entryNodes.getLength(); i++) {
                Node n = entryNodes.item(i);
                String nodeValue = n.getAttributes().getNamedItem("name").getNodeValue();
                if(nodeValue.startsWith("$")) {
                    System.out.println(nodeValue.substring(1, nodeValue.length()));
                }
            }
        }
    }
    

    The following code does:

    1. parse the document (your xml) into a DOM model.
    2. Create an Xpath expression for the property you wish to analyse. In this case, you want all nodes named "entry" regardless of where they are in the document. This is achieved by doing a // at the start of the Xpath //entry.
    3. Retrieve the name attribute of the entry node and check if it starts with a dollar-sign. 4.Print the Attribute value if it does start with a $ sign.

    The code then prints:

    ABC
    

    I hope this is what you were looking for.

    Alternatively this can be achieved with pure regex capturing every String that is surrounded by quote characters and starts with a dollar sign, as follows:

        Pattern pattern = Pattern.compile("\"\\$(.*)\"");
        Matcher matcher = pattern.matcher(xml);
        while(matcher.find()) {
            System.out.println(matcher.group(1));
        }