السلام عليكم :)
بما أن الهدف من الXML هو تخزين البيانات، فلا بد لنا في مرحلة من المراحل أن نسترجع هذه البيانات، أو بعضها، حسب شروط معينة. يمكن فعل ذلك يدويا، لكنه سيأخد مالانهاية من الوقت، يمكننا أيضا أن نعمل loop كل الnodes الموجودة في الdocument tree، لكن بما أننا مبرمجون فإننا كسالى ونبحث دائما عن الحلول البسيطة، والتي تتطلب أقل كود ممكن. الجافا وفرت لنا الحزمة javax.xml.xpath التي تتيح لنا استعمال XPath، وبالتالي البحث داخل المستندات xml بدون وجع رأس.
ما هو الXPath؟؟
إنشاء كائن Document يمثل المستند xml
إنشاء كائن XPath
البحث داخل المستند xml باستعمال XPath expressions
**********************************************************************************************************************
- ما هو الXPath؟؟
الXPath أو الXML Path Language هو لغة تتيح تصفح المستندات xml. فكما نستعمل URL للوصول لصفحة ما في الويب، أو مسار ملف ما في الfile system للوصول لهذا الملف، فإننا نستخدم XPath للوصول لعنصر ما داخل المستند xml
لنفترض المستند xml التالي
<?xml version="1.0" encoding="UTF-8"?> <phonebook> <person category="friend"> <name>Ahmed</name> <age>23</age> <sexe>male</sexe> <phone>0522222222</phone> <address>182 rue yyy</address> </person> <person category="friend"> <name>Sophia</name> <age>24</age> <sexe>female</sexe> <phone>0522333333</phone> <address>16 yyy street</address> </person> <person category="neighbour"> <name>Ali</name> <age>30</age> <sexe>male</sexe> <phone>0640444444</phone> <address>172 rue yyy</address> </person> <person category="neighbour"> <name>Samir</name> <age>28</age> <sexe>male</sexe> <phone>0660666666</phone> <address>180 rue yyy</address> </person> </phonebook>
التعببر التالي
/phonebook
يعني: إختر العنصر phonebook وكل أبنائه
في هذا التعبير
/phonebook/person[@category="friend"]
القوسين "[]" يسمحان لنا بتحديد شرط، والرمز "@" يعني أن العنصر عبارة عن attribute. إذن التعبير السابق يعني التالي: إختر جميع العناصر person التي تحتوي على الattribute category يساوي "friend".
/phonebook/person[age=30]
في هذا التعبير، الشرط هو أن يكون العنصر age يساوي 30، إذن التعبير سيعيد لنا كل العناصر person التي تحتوي على العنصر age المساوي ل30.
لمعرفة المزيد عن XPath :
http://www.w3schools...ath/default.asp
- إنشاء كائن Document يمثل المستند xml
بعد هذه اللمحة القصيرة عن XPath، نعود إلى الجافا. بما أننا ننوي التعامل مع مستند xml، فيجب علينا استرجاع كائن Document يمثل هذا المستند.
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document phoneBookDoc = docBuilder.parse(new File("phonebook.xml"));- إنشاء كائن XPath
الجافا توفر لنا الفئة XPath التي تمكننا من تنفيذ تعابير لغة XPath واختيار العناصر التي نريدها من المستند xml
أولا نسترجع الكائن XPathFactory
XPathFactory xpathFactory = XPathFactory.newInstance();
ثم نسترجع الكائن XPath
XPath xpath = xpathFactory.newXPath();
الآن يمكننا تنفيذ تعابير XPath، وذلك باستعمال الطريقة
evaluate(String expression, Object item, QName returnType)
المعطى الاول "expression" يمثل التعبير XPath الذي نريد تنفيذه
المعطى الثاني "item" يمثل السياق الذي سنبحث فيه، وهو غالبا يكون كائن Document يمثل المستند xml.
المعطى الثالث "returnType" يمثل نوع النتيجة التي ننتظرها. الأنواع التي يمكن أن نحصل عليها هي:
- XPathConstants.NODE : هذا النوع ممثل بالفئة Node، ونستعمله عندما تكون نتيجة التعبير XPath عنصرا واحدا فقط، أي node واحد فقط.
- XPathConstants.NODESET: هذا النوع ممثل بالفئة NodeList، ونستعمله عندما تكون نتيجة التعبير سلسلة من العناصر، وهو ما يستعمل في أغلب الحالات.
- XPathConstants.STRING: String
- XPathConstants.BOOLEAN: Boolean
- XPathConstants.NUMBER: Double
مثلا لو أردنا استرجاع العناصر "person" الذي تنتمي إلى الفئة "friend"، سنقوم بالتالي
String expression = "/phonebook/person[@category='friend']"; NodeList list = (NodeList)xpath.evaluate(expression, phoneBookDoc, XPathConstants.NODESET);
في المعطى "returnType" مررنا XPathConstants.NODESET لأننا ننتظر سلسلة من العناصر، أي كل العناصر "person" الذي تنتمي إلى الفئة "friend"
وإذا أردنا مثلا استرجاع العنصر الأول فقط "name" الموجود داخل "person" الذي تنتمي إلى الفئة "neighbour"، سنقوم بالتالي
String expression = "/phonebook/person[@category='neighbour']/name[1]"; Node name = (Node) xpath.evaluate(expression, phoneBookDoc, XPathConstants.NODE); System.out.println(name.getTextContent());
المعطى "returnType" يساوي هذا المرة NODE، لأننا اخترنا عنصرا واحدا فقط، وهو العنصر الأول.
مثال
import java.io.File;
import java.io.IOException;
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 AddressBook {
static void displayNodeList(NodeList list) {
for (int i = 0; i < list.getLength(); i++) {
Node person = list.item(i);
NodeList personInformations = person.getChildNodes();
for (int j = 0; j < personInformations.getLength(); j++) {
Node item = personInformations.item(j);
if (item.getNodeType() == Node.ELEMENT_NODE) {
System.out.println(item.getNodeName() + ": " + item.getTextContent());
}
}
}
}
public static void main(String[] args)
throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
//Get a Document object
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document phoneBookDoc = docBuilder.parse(new File("addressbook.xml"));
//Get an XPath object
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
String expression = "/phonebook/person[@category='friend']";
NodeList friends = (NodeList) xpath.evaluate(expression, phoneBookDoc, XPathConstants.NODESET);
displayNodeList(friends);
expression = "/phonebook/person[@category='neighbour']/name[1]";
Node nameFirstNeighbour = (Node) xpath.evaluate(expression, phoneBookDoc, XPathConstants.NODE);
System.out.println(nameFirstNeighbour.getTextContent());
}
}