เว็บเซอร์วิสของ Google Maps Platform คือชุดอินเทอร์เฟซ HTTP สำหรับบริการของ Google ที่ให้ข้อมูลทางภูมิศาสตร์สำหรับแอปพลิเคชันแผนที่
คู่มือนี้จะอธิบายแนวทางปฏิบัติทั่วไปที่เป็นประโยชน์ในการตั้งค่าคำขอบริการเว็บและประมวลผลคำตอบของบริการ โปรดดูเอกสารประกอบฉบับเต็มของ Directions API ในคู่มือนักพัฒนาซอฟต์แวร์
เว็บเซอร์วิสคืออะไร
เว็บเซอร์วิสของ Google Maps Platform เป็นอินเทอร์เฟซสำหรับการขอข้อมูล Maps API จากบริการภายนอกและการใช้ข้อมูลภายในแอปพลิเคชัน Maps บริการเหล่านี้ออกแบบมาเพื่อใช้ร่วมกับแผนที่ตามข้อจำกัดของใบอนุญาตในข้อกำหนดในการให้บริการของ Google Maps Platform
บริการบนเว็บของ Maps API ใช้คำขอ HTTP(S) ไปยัง URL ที่เฉพาะเจาะจง โดยส่งพารามิเตอร์ URL และ/หรือข้อมูล POST รูปแบบ JSON เป็นอาร์กิวเมนต์ไปยังบริการ โดยทั่วไปแล้ว บริการเหล่านี้จะแสดงผลข้อมูลในส่วนเนื้อหาของคำตอบเป็น JSON หรือ XML สำหรับการแยกวิเคราะห์และ/หรือการประมวลผลโดยแอปพลิเคชันของคุณ
คําขอ Directions API ทั่วไปมักจะอยู่ในรูปแบบต่อไปนี้
https://maps.googleapis.com/maps/api/directions/output?parameters
โดยที่ output
ระบุรูปแบบคำตอบ (ปกติจะเป็น json
หรือ xml
)
หมายเหตุ: แอปพลิเคชัน Directions API ทั้งหมดต้องมีการตรวจสอบสิทธิ์ ดูข้อมูลเพิ่มเติมเกี่ยวกับข้อมูลเข้าสู่ระบบสำหรับการตรวจสอบสิทธิ์
การเข้าถึง SSL/TLS
คำขอทั้งหมดของ Google Maps Platform ต้องใช้ HTTPS ซึ่งใช้คีย์ API หรือมีข้อมูลผู้ใช้ คำขอที่ส่งผ่าน HTTP ซึ่งมีข้อมูลที่ละเอียดอ่อนอาจถูกปฏิเสธ
การสร้าง URL ที่ถูกต้อง
คุณอาจคิดว่า URL "ที่ถูกต้อง" นั้นเข้าใจได้ง่ายๆ แต่จริงๆ แล้วไม่ใช่ เช่น URL ที่ป้อนภายในแถบที่อยู่ในเบราว์เซอร์อาจมีอักขระพิเศษ (เช่น "上海+中國"
) เบราว์เซอร์ต้องแปลอักขระเหล่านั้นเป็นการเข้ารหัสรูปแบบอื่นก่อนส่ง
ในทํานองเดียวกัน โค้ดที่สร้างหรือยอมรับอินพุต UTF-8 อาจถือว่า URL ที่มีอักขระ UTF-8 "ถูกต้อง" แต่ก็ต้องแปลอักขระเหล่านั้นก่อนส่งไปยังเว็บเซิร์ฟเวอร์ด้วย
กระบวนการนี้เรียกว่า
การเข้ารหัส URL หรือการเข้ารหัสด้วยเปอร์เซ็นต์
อักขระพิเศษ
เราต้องแปลอักขระพิเศษเนื่องจาก URL ทั้งหมดต้องเป็นไปตามรูปแบบคำสั่งที่ระบุไว้ในข้อกำหนด Uniform Resource Identifier (URI) ซึ่งหมายความว่า URL ต้องมีเฉพาะชุดย่อยพิเศษของอักขระ ASCII ได้แก่ สัญลักษณ์ตัวอักษรและตัวเลขที่คุ้นเคย และอักขระที่สงวนไว้บางตัวเพื่อใช้เป็นอักขระควบคุมภายใน URL ตารางนี้สรุปอักขระเหล่านี้
ตั้งค่า | อักขระ | การใช้งาน URL |
---|---|---|
ตัวอักษรและตัวเลขคละกัน | a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 | สตริงข้อความ การใช้รูปแบบ (http ) พอร์ต (8080 ) ฯลฯ |
ไม่ได้จอง | - _ . ~ | สตริงข้อความ |
จองแล้ว | ! * ' ( ) ; : @ & = + $ , / ? % # [ ] | อักขระควบคุมและ/หรือสตริงข้อความ |
เมื่อสร้าง URL ที่ถูกต้อง คุณต้องตรวจสอบว่า URL ดังกล่าวมีเฉพาะอักขระที่แสดงในตารางเท่านั้น โดยทั่วไป การทำให้ URL ใช้ชุดอักขระนี้ทำให้เกิดปัญหา 2 อย่าง ได้แก่ การละเว้นและการแทนที่
- อักขระที่คุณต้องการจัดการอยู่นอกชุดข้างต้น ตัวอย่างเช่น อักขระในภาษาต่างประเทศ เช่น
上海+中國
ต้องได้รับการเข้ารหัสโดยใช้อักขระข้างต้น ตามธรรมเนียมที่นิยมกัน มักจะใช้อักขระบวก'+'
เพื่อแทนที่เว้นวรรค (ซึ่งไม่อนุญาตใน URL) ด้วย - อักขระที่อยู่ในชุดข้างต้นเป็นอักขระที่สงวนไว้ แต่ต้องใช้ตามตัวอักษร
เช่น
?
ใช้ภายใน URL เพื่อระบุจุดเริ่มต้นของสตริงการค้นหา หากต้องการใช้สตริง "? and the Mysterions" คุณจะต้องเข้ารหัสอักขระ'?'
อักขระทั้งหมดที่จะเข้ารหัส URL จะได้รับการเข้ารหัสโดยใช้อักขระ '%'
และค่าฐาน 16 2 อักขระที่สอดคล้องกับอักขระ UTF-8 ตัวอย่างเช่น 上海+中國
ใน UTF-8 จะเป็น%E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B
เมื่อเข้ารหัสเป็น URL สตริง ? and the Mysterians
จะมีการเข้ารหัส URL เป็น %3F+and+the+Mysterians
หรือ %3F%20and%20the%20Mysterians
อักขระทั่วไปที่ต้องเข้ารหัส
อักขระทั่วไปบางตัวที่ต้องเข้ารหัส ได้แก่
อักขระที่ไม่ปลอดภัย | ค่าที่เข้ารหัส |
---|---|
Space | %20 |
" | %22 |
< | %3C |
> | %3E |
# | %23 |
% | %25 |
| | %7C |
บางครั้งการแปลง URL ที่คุณได้รับจากอินพุตของผู้ใช้อาจเป็นเรื่องยาก เช่น ผู้ใช้อาจป้อนที่อยู่เป็น "5th&Main St." โดยทั่วไป คุณควรสร้าง URL จากส่วนต่างๆ โดยถือว่าอินพุตของผู้ใช้คืออักขระตามตัวอักษร
นอกจากนี้ URL ของบริการเว็บและ Web API แบบคงที่ทั้งหมดของ Google Maps Platform จะถูกจำกัดไว้ที่ 16384 อักขระ สำหรับบริการส่วนใหญ่ คุณจะไม่ค่อยถึงขีดจำกัดอักขระนี้ อย่างไรก็ตาม โปรดทราบว่าบริการบางอย่างมีพารามิเตอร์หลายรายการที่อาจส่งผลให้ URL ยาว
การใช้ Google APIs อย่างสุภาพ
ไคลเอ็นต์ API ที่ออกแบบมาไม่ดีอาจทำให้ทั้งอินเทอร์เน็ตและเซิร์ฟเวอร์ของ Google ทำงานหนักเกินความจำเป็น ส่วนนี้มีแนวทางปฏิบัติแนะนำบางส่วนสำหรับไคลเอ็นต์ของ API การปฏิบัติตามแนวทางปฏิบัติแนะนำเหล่านี้จะช่วยให้แอปพลิเคชันของคุณไม่ถูกบล็อกเนื่องจากการละเมิด API โดยไม่ได้ตั้งใจ
Exponential Backoff
ในบางกรณีที่พบไม่บ่อยนัก อาจมีบางอย่างผิดพลาดในการส่งคำขอ คุณอาจได้รับโค้ดตอบกลับ HTTP 4XX หรือ 5XX หรือการเชื่อมต่อ TCP อาจไม่สำเร็จระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์ของ Google บางครั้งการลองส่งคำขออีกครั้งก็อาจคุ้มค่า เนื่องจากคำขอติดตามผลอาจสำเร็จได้เมื่อคำขอแรกไม่สำเร็จ อย่างไรก็ตาม สิ่งสำคัญคืออย่าทำซ้ำๆ โดยส่งคำขอไปยังเซิร์ฟเวอร์ของ Google ลักษณะการทำงานแบบวนซ้ำนี้อาจทำให้เครือข่ายระหว่างไคลเอ็นต์กับ Google ทำงานหนักเกินไปและก่อให้เกิดปัญหากับหลายฝ่าย
วิธีที่ดีกว่านั้นคือลองอีกครั้งโดยเพิ่มความล่าช้าระหว่างการลอง โดยปกติแล้วความล่าช้าจะเพิ่มขึ้นตามปัจจัยการคูณทุกครั้งที่พยายาม ซึ่งเรียกว่าExponential Backoff
ตัวอย่างเช่น ลองพิจารณาแอปพลิเคชันที่ต้องการให้ส่งคําขอนี้ไปยัง API เขตเวลา
https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510×tamp=1331161200&key=YOUR_API_KEY
ตัวอย่าง Python ต่อไปนี้แสดงวิธีส่งคำขอด้วยการถดถอยแบบทวีคูณ
import json import time import urllib.error import urllib.parse import urllib.request # The maps_key defined below isn't a valid Google Maps API key. # You need to get your own API key. # See https://developers.google.com/maps/documentation/timezone/get-api-key API_KEY = "YOUR_KEY_HERE" TIMEZONE_BASE_URL = "https://maps.googleapis.com/maps/api/timezone/json" def timezone(lat, lng, timestamp): # Join the parts of the URL together into one string. params = urllib.parse.urlencode( {"location": f"{lat},{lng}", "timestamp": timestamp, "key": API_KEY,} ) url = f"{TIMEZONE_BASE_URL}?{params}" current_delay = 0.1 # Set the initial retry delay to 100ms. max_delay = 5 # Set the maximum retry delay to 5 seconds. while True: try: # Get the API response. response = urllib.request.urlopen(url) except urllib.error.URLError: pass # Fall through to the retry loop. else: # If we didn't get an IOError then parse the result. result = json.load(response) if result["status"] == "OK": return result["timeZoneId"] elif result["status"] != "UNKNOWN_ERROR": # Many API errors cannot be fixed by a retry, e.g. INVALID_REQUEST or # ZERO_RESULTS. There is no point retrying these requests. raise Exception(result["error_message"]) if current_delay > max_delay: raise Exception("Too many retry attempts.") print("Waiting", current_delay, "seconds before retrying.") time.sleep(current_delay) current_delay *= 2 # Increase the delay each time we retry. if __name__ == "__main__": tz = timezone(39.6034810, -119.6822510, 1331161200) print(f"Timezone: {tz}")
นอกจากนี้ คุณควรตรวจสอบด้วยว่าไม่มีโค้ดลองอีกครั้งที่สูงกว่าในเชนการเรียกแอปพลิเคชัน ซึ่งทําให้เกิดการขอซ้ำหลายครั้งติดต่อกัน
คำขอที่ซิงค์
คำขอที่ซิงค์จำนวนมากไปยัง API ของ Google อาจดูเหมือนการโจมตีแบบปฏิเสธการให้บริการแบบกระจาย (DDoS) โครงสร้างพื้นฐานของ Google และระบบอาจดำเนินการกับคำขอดังกล่าวตามความเหมาะสม หากต้องการหลีกเลี่ยงปัญหานี้ คุณควรตรวจสอบว่าคำขอ API ไม่ได้ซิงค์กันระหว่างไคลเอ็นต์
ตัวอย่างเช่น ลองพิจารณาแอปพลิเคชันที่แสดงเวลาในเขตเวลาปัจจุบัน แอปพลิเคชันนี้อาจตั้งปลุกในระบบปฏิบัติการไคลเอ็นต์เพื่อปลุกระบบเมื่อเริ่มนาทีเพื่อให้อัปเดตเวลาที่แสดงได้ แอปพลิเคชันควรไม่เรียก API ใดๆ เป็นส่วนหนึ่งของการประมวลผลที่เกี่ยวข้องกับการแจ้งเตือนนั้น
การเรียก API เพื่อตอบสนองต่อการปลุกแบบคงที่นั้นไม่ดีเนื่องจากจะทำให้การเรียก API ซิงค์กับช่วงเริ่มต้นของนาที แม้จะเป็นระหว่างอุปกรณ์ต่างๆ ก็ตาม แทนที่จะกระจายอย่างสม่ำเสมอเมื่อเวลาผ่านไป แอปพลิเคชันที่ออกแบบมาไม่ดีซึ่งทําเช่นนี้จะทําให้การเข้าชมเพิ่มขึ้นเป็น 60 เท่าของระดับปกติในช่วงเริ่มต้นของแต่ละนาที
แต่การออกแบบที่ดีอย่างหนึ่งอาจเป็นการตั้งปลุกครั้งที่ 2 เป็นเวลาที่เลือกแบบสุ่ม เมื่อการแจ้งเตือนครั้งที่ 2 นี้เริ่มทำงาน แอปพลิเคชันจะเรียกใช้ API ที่จำเป็นและจัดเก็บผลลัพธ์ เมื่อแอปพลิเคชันต้องการอัปเดตการแสดงผลเมื่อเริ่มนาทีใหม่ ก็จะใช้ผลลัพธ์ที่เก็บไว้ก่อนหน้านี้แทนการเรียก API อีกครั้ง เมื่อใช้วิธีนี้ การเรียก API จะกระจายอย่างสม่ำเสมอเมื่อเวลาผ่านไป นอกจากนี้ การเรียก API จะไม่ทำให้การแสดงผลล่าช้าเมื่อมีการอัปเดตจอแสดงผล
นอกจากเวลาเริ่มต้นของนาทีแล้ว ช่วงเวลาอื่นๆ ของการซิงค์ที่พบบ่อยซึ่งคุณควรไม่กำหนดเป้าหมาย ได้แก่ เวลาเริ่มต้นของชั่วโมง และเวลาเริ่มต้นของแต่ละวันตอนเที่ยงคืน
การประมวลผลการตอบกลับ
ส่วนนี้จะอธิบายวิธีดึงค่าเหล่านี้แบบไดนามิกจากการตอบกลับของเว็บเซอร์วิส
เว็บเซอร์วิสของ Google Maps ให้คำตอบที่เข้าใจง่าย แต่ไม่ค่อยเป็นมิตรกับผู้ใช้ เมื่อทำการค้นหา คุณอาจต้องการดึงค่าที่เฉพาะเจาะจง 2-3 ค่าแทนการแสดงชุดข้อมูล โดยทั่วไป คุณจะต้องแยกวิเคราะห์คําตอบจากบริการเว็บและดึงเฉพาะค่าที่คุณสนใจ
รูปแบบการแยกวิเคราะห์ที่คุณใช้จะขึ้นอยู่กับว่าคุณแสดงผลลัพธ์เป็น XML หรือ JSON การตอบกลับ JSON อยู่ในรูปแบบออบเจ็กต์ JavaScript อยู่แล้ว จึงอาจประมวลผลภายใน JavaScript บนไคลเอ็นต์ การตอบกลับด้วย XML ควรประมวลผลโดยใช้โปรแกรมประมวลผล XML และภาษาการค้นหา XML เพื่อจัดการกับองค์ประกอบภายในรูปแบบ XML เราใช้ XPath ในตัวอย่างต่อไปนี้ เนื่องจากเป็นรูปแบบที่รองรับโดยทั่วไปในไลบรารีการประมวลผล XML
ประมวลผล XML ด้วย XPath
XML เป็นรูปแบบข้อมูลที่มีโครงสร้างที่ค่อนข้างสมบูรณ์ซึ่งใช้สําหรับการแลกเปลี่ยนข้อมูล แม้ว่าจะไม่เบาเท่า JSON แต่ XML รองรับภาษาได้มากกว่าและมีเครื่องมือที่มีประสิทธิภาพมากกว่า ตัวอย่างเช่น โค้ดสําหรับการประมวลผล XML ใน Java จะฝังอยู่ในแพ็กเกจ javax.xml
เมื่อประมวลผลการตอบกลับ XML คุณควรใช้ภาษาการค้นหาที่เหมาะสมเพื่อเลือกโหนดภายในเอกสาร XML แทนที่จะถือว่าองค์ประกอบอยู่ในตําแหน่งสัมบูรณ์ภายในมาร์กอัป XML XPath เป็นไวยากรณ์ภาษาสําหรับอธิบายโหนดและองค์ประกอบในเอกสาร XML ที่ไม่ซ้ำกัน นิพจน์ XPath ช่วยให้คุณระบุเนื้อหาที่เฉพาะเจาะจงภายในเอกสารคำตอบ XML ได้
นิพจน์ XPath
ความคุ้นเคยกับ XPath จะช่วยให้คุณพัฒนารูปแบบการแยกวิเคราะห์ที่มีประสิทธิภาพได้ ส่วนนี้จะเน้นที่วิธีระบุองค์ประกอบภายในเอกสาร XML ด้วย XPath ซึ่งช่วยให้คุณระบุองค์ประกอบหลายรายการและสร้างการค้นหาที่ซับซ้อนได้
XPath ใช้นิพจน์เพื่อเลือกองค์ประกอบภายในเอกสาร XML โดยใช้ไวยากรณ์ที่คล้ายกับที่ใช้สำหรับเส้นทางไดเรกทอรี นิพจน์เหล่านี้จะระบุองค์ประกอบภายในต้นไม้เอกสาร XML ซึ่งเป็นต้นไม้ตามลําดับชั้นคล้ายกับ DOM โดยทั่วไปแล้ว นิพจน์ XPath จะทำงานอย่างกว้างขวาง ซึ่งหมายความว่าจะจับคู่กับโหนดทั้งหมดที่ตรงกับเกณฑ์ที่ระบุ
เราจะใช้ XML ตัวอย่างต่อไปนี้เพื่อแสดงตัวอย่าง
<WebServiceResponse> <status>OK</status> <result> <type>sample</type> <name>Sample XML</name> <location> <lat>37.4217550</lat> <lng>-122.0846330</lng> </location> </result> <result> <message>The secret message</message> </result> </WebServiceResponse>
การเลือกโหนดในนิพจน์
การเลือก XPath จะเลือกโหนด โหนดรูทจะครอบคลุมทั้งเอกสาร คุณเลือกโหนดนี้โดยใช้นิพจน์พิเศษ "/
" โปรดทราบว่าโหนดรูทไม่ใช่โหนดระดับบนสุดของเอกสาร XML แต่อยู่เหนือองค์ประกอบระดับบนสุดนี้ 1 ระดับและรวมองค์ประกอบดังกล่าวไว้ด้วย
โหนดองค์ประกอบแสดงองค์ประกอบต่างๆ ภายในลําดับชั้นเอกสาร XML ตัวอย่างเช่น องค์ประกอบ <WebServiceResponse>
จะแสดงถึงองค์ประกอบระดับบนสุดที่แสดงในบริการตัวอย่างด้านบน คุณเลือกโหนดแต่ละโหนดได้ผ่านเส้นทางแบบสัมบูรณ์หรือแบบสัมพัทธ์ ซึ่งระบุด้วยการมีหรือไม่มีอักขระ "/
" นําหน้า
- เส้นทางแบบสัมบูรณ์: นิพจน์ "
/WebServiceResponse/result
" จะเลือกโหนด<result>
ทั้งหมดที่เป็นโหนดย่อยของโหนด<WebServiceResponse>
(โปรดทราบว่าองค์ประกอบทั้ง 2 รายการนี้มาจากโหนดรูท "/
") - เส้นทางแบบสัมพัทธ์จากบริบทปัจจุบัน: นิพจน์ "
result
" จะจับคู่กับองค์ประกอบ<result>
ภายในบริบทปัจจุบัน โดยทั่วไปแล้ว คุณไม่จำเป็นต้องกังวลเกี่ยวกับบริบท เนื่องจากปกติแล้วคุณประมวลผลผลการค้นหาบริการบนเว็บผ่านนิพจน์เดียว
นิพจน์ใดนิพจน์หนึ่งเหล่านี้อาจเพิ่มด้วยการเพิ่มเส้นทางไวลด์การ์ด ซึ่งระบุด้วยเครื่องหมายทับคู่ ("//
") ไวลด์การ์ดนี้บ่งบอกว่าอาจมีองค์ประกอบที่ตรงกันตั้งแต่ 0 รายการขึ้นไปในเส้นทางที่แทรกอยู่ ตัวอย่างเช่น นิพจน์ XPath "//formatted_address
" จะจับคู่กับโหนดทั้งหมดที่มีชื่อนั้นในเอกสารปัจจุบัน
นิพจน์ //viewport//lat
จะจับคู่กับองค์ประกอบ <lat>
ทั้งหมดที่ติดตาม <viewport>
ในฐานะองค์ประกอบหลักได้
โดยค่าเริ่มต้น นิพจน์ XPath จะจับคู่กับองค์ประกอบทั้งหมด คุณสามารถจํากัดนิพจน์ให้จับคู่กับองค์ประกอบที่เฉพาะเจาะจงได้โดยระบุพริเนกต์ ซึ่งอยู่ภายในวงเล็บเหลี่ยม ([]
) ตัวอย่างเช่น นิพจน์ XPath "/GeocodeResponse/result[2]
จะแสดงผลลัพธ์ที่ 2 เสมอ
ประเภทนิพจน์ | |
---|---|
โหนดราก | นิพจน์ XPath: "
/ "การเลือก:
<WebServiceResponse> <status>OK</status> <result> <type>sample</type> <name>Sample XML</name> <location> <lat>37.4217550</lat> <lng>-122.0846330</lng> </location> </result> <result> <message>The secret message</message> </result> </WebServiceResponse> |
Absolute Path | นิพจน์ XPath: "
/WebServiceResponse/result "การเลือก:
<result> <type>sample</type> <name>Sample XML</name> <location> <lat>37.4217550</lat> <lng>-122.0846330</lng> </location> </result> <result> <message>The secret message</message> </result> |
เส้นทางที่มีไวลด์การ์ด | นิพจน์ XPath: "
/WebServiceResponse//location "การเลือก:
<location> <lat>37.4217550</lat> <lng>-122.0846330</lng> </location> |
เส้นทางที่มีพรอมต์ | นิพจน์ XPath: "
/WebServiceResponse/result[2]/message "การเลือก:
<message>The secret message</message> |
รายการย่อยโดยตรงทั้งหมดของ result รายการแรก |
นิพจน์ XPath: "
/WebServiceResponse/result[1]/* "การเลือก:
<type>sample</type> <name>Sample XML</name> <location> <lat>37.4217550</lat> <lng>-122.0846330</lng> </location> |
name ของ
result ที่มีข้อความ type เป็น "ตัวอย่าง" |
นิพจน์ XPath: "
/WebServiceResponse/result[type/text()='sample']/name "การเลือก:
Sample XML |
โปรดทราบว่าเมื่อเลือกองค์ประกอบ คุณจะเลือกโหนด ไม่ใช่แค่ข้อความภายในออบเจ็กต์เหล่านั้น โดยทั่วไปแล้ว คุณจะต้องวนผ่านโหนดที่ตรงกันทั้งหมดและดึงข้อมูลข้อความ นอกจากนี้ คุณยังจับคู่โหนดข้อความโดยตรงได้ด้วย ดูโหนดข้อความ ด้านล่าง
โปรดทราบว่า XPath รองรับโหนดแอตทริบิวต์ด้วย อย่างไรก็ตาม เว็บเซอร์วิสของ Google Maps ทั้งหมดจะแสดงองค์ประกอบที่ไม่มีแอตทริบิวต์ คุณจึงไม่จำเป็นต้องจับคู่แอตทริบิวต์
การเลือกข้อความในนิพจน์
ข้อความภายในเอกสาร XML จะระบุไว้ในนิพจน์ XPath
ผ่านโอเปอเรเตอร์ text node โอเปอเรเตอร์ "text()
" นี้บ่งบอกถึงการดึงข้อความจากโหนดที่ระบุ ตัวอย่างเช่น นิพจน์ XPath "//formatted_address/text()
" จะแสดงผลข้อความทั้งหมดภายในองค์ประกอบ <formatted_address>
ประเภทนิพจน์ | |
---|---|
โหนดข้อความทั้งหมด (รวมถึงเว้นวรรค) | นิพจน์ XPath: "
//text() "การเลือก:
sample Sample XML 37.4217550 -122.0846330 The secret message |
การเลือกข้อความ | นิพจน์ XPath: "
/WebServiceRequest/result[2]/message/text() "การเลือก:
The secret message |
การเลือกแบบคำนึงถึงบริบท | นิพจน์ XPath: "
/WebServiceRequest/result[type/text() = 'sample']/name/text() "การเลือก:
Sample XML |
หรือจะประเมินนิพจน์และแสดงผลชุดโหนด แล้ววนซ้ำ "ชุดโหนด" นั้นเพื่อดึงข้อความจากแต่ละโหนดก็ได้ เราใช้แนวทางนี้ในตัวอย่างด้านล่าง
ดูข้อมูลเพิ่มเติมเกี่ยวกับ XPath ได้ในข้อกำหนด W3C ของ XPath
การประเมิน XPath ใน Java
Java รองรับการแยกวิเคราะห์ XML และการใช้นิพจน์ XPath อย่างกว้างขวางในแพ็กเกจ javax.xml.xpath.*
ด้วยเหตุนี้ โค้ดตัวอย่างในส่วนนี้จึงใช้ Java เพื่อแสดงวิธีจัดการ XML และแยกวิเคราะห์ข้อมูลจากคำตอบของบริการ XML
หากต้องการใช้ XPath ในโค้ด Java ก่อนอื่นคุณต้องสร้างอินสแตนซ์ของ XPathFactory
และเรียกใช้ newXPath()
ในฟีเจอร์นั้นเพื่อสร้างออบเจ็กต์ XPath
จากนั้นออบเจ็กต์นี้จะประมวลผล XML ที่ส่งมาและนิพจน์ XPath โดยใช้เมธอด evaluate()
เมื่อประเมินนิพจน์ XPath โปรดตรวจสอบว่าคุณวนซ้ำ "ชุดโหนด" ที่เป็นไปได้ซึ่งอาจแสดงผล เนื่องจากผลลัพธ์เหล่านี้จะแสดงผลเป็นโหนด DOM ในโค้ด Java คุณจึงควรบันทึกค่าหลายค่าดังกล่าวภายในออบเจ็กต์ NodeList
และวนซ้ำออบเจ็กต์นั้นเพื่อดึงข้อความหรือค่าจากโหนดเหล่านั้น
โค้ดต่อไปนี้แสดงวิธีสร้างออบเจ็กต์ XPath
กำหนด XML และนิพจน์ XPath ให้กับออบเจ็กต์ และประเมินนิพจน์เพื่อพิมพ์เนื้อหาที่เกี่ยวข้อง
import org.xml.sax.InputSource; import org.w3c.dom.*; import javax.xml.xpath.*; import java.io.*; public class SimpleParser { public static void main(String[] args) throws IOException { XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); try { System.out.print("Web Service Parser 1.0\n"); // In practice, you'd retrieve your XML via an HTTP request. // Here we simply access an existing file. File xmlFile = new File("XML_FILE"); // The xpath evaluator requires the XML be in the format of an InputSource InputSource inputXml = new InputSource(new FileInputStream(xmlFile)); // Because the evaluator may return multiple entries, we specify that the expression // return a NODESET and place the result in a NodeList. NodeList nodes = (NodeList) xpath.evaluate("XPATH_EXPRESSION", inputXml, XPathConstants.NODESET); // We can then iterate over the NodeList and extract the content via getTextContent(). // NOTE: this will only return text for element nodes at the returned context. for (int i = 0, n = nodes.getLength(); i < n; i++) { String nodeString = nodes.item(i).getTextContent(); System.out.print(nodeString); System.out.print("\n"); } } catch (XPathExpressionException ex) { System.out.print("XPath Error"); } catch (FileNotFoundException ex) { System.out.print("File Error"); } } }