开发者

using conditions in XPath expressions

开发者 https://www.devze.com 2023-01-09 22:45 出处:网络
I need to parse through an XML document in the database and search for a given expression in it. Then, I must return a String value if the given expression is present in the XML else I need to parse t

I need to parse through an XML document in the database and search for a given expression in it. Then, I must return a String value if the given expression is present in the XML else I need to parse through the next expression and return another String value and so on.

I achieved this by using the following code:

// An xml document is passed as a Node when getEntryType() method is called

 public static class XMLTextFields {
        public static String getEntryType(Node target) throws XPathExpressionException {
          XPathFactory factory = XPathFactory.newInstance();
          XPath xpath = factory.newXpath();
          String entryType = null;
          String [] expression = new String [] {"./libx:package", "./libx:libapp", "./libx:module"};

          String [] type = new String [] {"Package", "Libapp", "Module" };
          for (int i = 0; i < 3; i ++) {
              XPathExpression expr = xpath.compile(expression[i]);
              Object result = expr.evaluate(target, XPathConstants.NODESET);
              NodeList nodes = (NodeList) result;
              if (nodes.getLength() == 0)
                  continue;
              entryType = (type[i]);
          }
         开发者_Python百科 return entryType;
        }
    }

I am wondering if there is a simpler way to do this? Meaning, is there a way to use the "expression" like a function which returns a string if the expression is present in the xml.

I am guessing I should be able to do something like this but am not exactly sure:

String [] Expression = new String [] {"[./libx:package]\"Package\"", ....} 

Meaning, return "Package" if libx:package node exists in the given XML


If your XPath processor is version 2, you can use if expressions: http://www.w3.org/TR/xpath20/#id-conditionals .


You can use XSLT here. In XSLT you can check the node name by using

<xsl:value-of select="*[starts-with(name(),'libx:package')]" />

OR you can check using

<xsl:if select="name()='libx:package'" > <!-- Your cusotm elements here... --> </xsl:if>

You can check existence of Element OR Attribute this way to validate specific needs.

hope this helps.


Yes there is, just use an XPath functions in your expression:

Expression exp = xpath.compile("local-name(*[local-name() = 'package'])")
// will return "package" for any matching elements
exp.evaluate(target, XPathConstants.STRING); 

But this will return "package" instead of "Package". Note the capital P

Below is the Test code:

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
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 java.util.Map;
import java.util.HashMap;

public class Test {
       private static Map<String, String> mappings = new HashMap<String, String>();
       static {
          mappings.put("package", "Package");
          mappings.put("libapp", "Application");
          mappings.put("module", "Module");
       }

       public static void main(String[] args) throws Throwable {
          XPathFactory factory = XPathFactory.newInstance();
          XPath xpath = factory.newXPath();
          String entryType = null;
          XPathExpression [] expressions = new XPathExpression[] {
             xpath.compile("local-name(*[local-name() = 'package'])"),
             xpath.compile("local-name(*[local-name() = 'libapp'])"),
             xpath.compile("local-name(*[local-name() = 'module'])")
          };

          DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance();
          DocumentBuilder parser = fac.newDocumentBuilder();
          Document doc = parser.parse(args[0]);

          for(int i = 0; i < expressions.length; i++) {
            String found = (String) expressions[i].evaluate(doc.getDocumentElement(),
                          XPathConstants.STRING);
            entryType  = mappings.get(found);
            if(entryType != null && !entryType.trim().isEmpty())   {
               break;
            }
          }

          System.out.println(entryType);

       }
}

Contents of text file:

<?xml version="1.0"?>
<root xmlns:libx="urn:libex">
   <libx:package>mypack</libx:package>
   <libx:libapp>myapp</libx:libapp>
   <libx:module>mymod</libx:module>
</root>


In XPath 1.0

concat(translate(substring(local-name(libx:package|libx:libapp|libx:module),
                           1,
                           1),
                 'plm',
                 'PLM'),
       substring(local-name(libx:package|libx:libapp|libx:module),2))

EDIT: It was dificult to understand the path because there was not provided input sample...


@ALL: Thanks!

I used:

XPathExpression expr = xpath.compile("concat(substring('Package',0,100*boolean(//libx:package))," + "substring('Libapp',0,100*boolean(//libx:libapp)),substring('Module',0,100*boolean(//libx:module)))"); expr.evaluate(target, XPathConstants.STRING);

0

精彩评论

暂无评论...
验证码 换一张
取 消