-1

I have the following code to find type of required node.

  private void handleDemote(CalendarCustomization calendar)
{
    String name = calendar.getName();
    Node node = (Node)reader.read("/APIBusinessObjects/Calendar[Name='" + name + "']/Type", XPathConstants.NODE);
   ...}

  public Object read(String expression, QName returnType)
{
    try
    {
        XPathExpression xPathExpression = xPath.compile(expression);
        return xPathExpression.evaluate(xmlDocument, returnType);
    }
    catch (XPathExpressionException ex)
    {
        ex.printStackTrace();
        return null;
    }
}

The xml which I am trying to parse has te following content

 <Calendar>
    <BaseCalendarObjectId xsi:nil="true" />
    <HoursPerDay>8</HoursPerDay>
    <HoursPerMonth>173.3</HoursPerMonth>
    <HoursPerWeek>40</HoursPerWeek>
    <HoursPerYear>2080</HoursPerYear>
    <IsDefault>0</IsDefault>
    <IsPersonal>0</IsPersonal>
    <Name>test&apos;sCal</Name>

The getName function is returning me the test'sCal.So name =test'sCal . The problem is with the apostrophe as the expression contains single extra quote. it shortens the name causing the expression to become wrong. Please suggest .

jetty
  • 859
  • 2
  • 17
  • 37

2 Answers2

1

According to this answer, you should be able to use XPath variables in Java, and that is the correct way to go about this.

You can define a generic variable resolver:

class MapVariableResolver implements XPathVariableResolver {
  // local store of variable name -> variable value mappings
  Map<String, String> variableMappings = new HashMap<String, String>();

  // a way of setting new variable mappings 
  public void setVariable(String key, String value)  {
    variableMappings.put(key, value);
  }

  // override this method in XPathVariableResolver to 
  // be used during evaluation of the XPath expression      
  @Override
  public Object resolveVariable(QName varName) {
    // if using namespaces, there's more to do here
    String key = varName.getLocalPart();
    return variableMappings.get(key);
  }
}

modify your read() method like this:

public Object read(String expression, QName returnType, XPathVariableResolver vr)
{
    try
    {
        xPath.setXPathVariableResolver(vr != null ? vr : new MapVariableResolver());
        XPathExpression xPathExpression = xPath.compile(expression);
        return xPathExpression.evaluate(xmlDocument, returnType);
    }
    catch (XPathExpressionException ex)
    {
        ex.printStackTrace();
        return null;
    }
}

and then do this:

String name = calendar.getName();
MapVariableResolver vr = new MapVariableResolver() ;
vr.setVariable("name", name);

Node node = (Node)reader.read("/APIBusinessObjects/Calendar[Name = $name]/Type",
                              XPathConstants.NODE, vr);
Community
  • 1
  • 1
JLRishe
  • 99,490
  • 19
  • 131
  • 169
0

For a general solution (i.e. when you don't know whether the input will contain single quotes, double quotes, or both):

  1. If you have XPath 2.0, which I guess you don't judging by your Java code, you could replace each single quote with a pair of single quotes (in string delimited by single quotes, as yours is). (See this answer.)

  2. Otherwise, you can use concat() within your XPath expression to concatenate '"' and "'" with the rest of your string as needed. See The Perils of XPath Expressions (Specifically, Escaping Quotes). So with your example data, your XPath expression would come out as:

-

 /APIBusinessObjects/Calendar[Name = concat('test', "'", 'sCal')]

Then it's up to you to write a Java function to transform test'sCal into 'test', "'", 'sCal'. Thankfully, concat() will take as many arguments as you give it.

Community
  • 1
  • 1
LarsH
  • 27,481
  • 8
  • 94
  • 152