חלק 3: מבוא ל- XPath XML Path Language Spring 2005
מסמך דוגמא <bib> <book price=“55”> <publisher>Addison-Wesley</publisher> <author>Serge Abiteboul</author> <author> <first-name>Rick</first-name> <last-name>Hull</last-name> </author> <author>Victor Vianu</author> <title>Foundations of Databases</title> <year>1995</year> </book> <book> <publisher>Freeman</publisher> <author>Jeffrey D. Ullman</author> <title>Principles of Database and Knowledge Base Systems</title> <year>1998</year> </book> </bib> Spring 2005
מסמך XML כעץ צומת השורש צומת המסמך . . . . bib book book price=55 publisher author . . . . Addison-Wesley Serge Abiteboul Spring 2005
ביטויי XPath – דוגמאות פשוטות /bib/book/year התוצאה: <year>1995</year> <year>1998</year> /bib/paper/year קבוצה ריקה של צמתים (אין אלמנטים בעלי שם paper) לשים דגש על כך שחוזרת לנו צומת מתחילת התג ועד סוף התג כולל כל מה שבאמצע. Spring 2005
חיפוש צאצאים (סגור Kleene מוגבל) //author התוצאה: <author>Serge Abiteboul</author> <author> <first-name>Rick</first-name> <last-name>Hull</last-name> </author> <author>Victor Vianu</author> <author>Jeffrey D. Ullman</author> /bib//first-name קבוצה של 4 צמתים Spring 2005
בחירת צמתים שאינם אלמנטים text() מחזיר צמתים מסוג טקסט node() מחזיר כל צמת ללא חשיבות לסוגו הביטוי הבא /bib/book/author/text() מחזיר את שמות הסופרים ששמם נמצא בצומת טקסט אחד. Serge Abiteboul Victor Vianu Jeffrey D. Ullman הסופר Rick Hull אינו מופיע משום ששמו מופרד לשני אלמנטים, כלומר לאלמנט author לא קיים צומת בן מסוג טקסט. עד עכשיו בחרנו ספציפית את שם הצומת שרצינו, אבל בחרנו רק אלמנטים. ניתן לבחור גם: צומת טקסט ע"י שימוש ב-text() למציאת הטקסט שמתחת לצומת אלמנט. צומת תכונות ע"י שימוש ב-@ לפני שם התכונה. כל התכונות ע"י שימוש ב-@* כל האלמנטים ע"י שימוש ב-* (למעשה זה כל הצמתים מהסוג של ציר החיפוש. לכן @* יחזיר את כל הצמתים מסוג תכונה. מאחר וציר החיפוש הוא של תכונות) כל הצמתים מכל הסוגים ע"י שימוש ב-node(). הייחודי בצומת תכונה הוא שהאלמנט שבה נמצאת התכונה הוא האבא של צומת התכונה. אבל צומת התכונה אינו הבן של צומת האב. משום כך node() לא יחזיר צמתי תכונות כי הן לא בנים של האלמנט. לעומת זאת @node() כן יחזיר את כל צמתי התכונות. כי הוא מחפש את כל סוגי הצמתים שהם תכונות של האלמנט (או בקיצור כל צמתי התכונות של האלמנט) Spring 2005
בחירת אלמנט כלשהו - wildcard //author/* התוצאה: <first-name>Rick</first-name> <last-name>Hull</last-name> ה-wildcard * במקרה זה בוחר כל צומת אלמנט ללא חשיבות לשמו. Spring 2005
גישה לתכונות /bib/book/@price התוצאה: “55” ה-@ מתייחס לתכונות ה-@ מתייחס לתכונות ה-@price מתייחס לתכונה price @* מתייחס לתכונה כל שהיא Spring 2005
בחירה לפי ביטויים בוליאניים /bib/book/author[first-name = “Rick”] התוצאה: <author> <first-name>Rick</first-name> <last-name>Hull</last-name> </author> הביטוי בתוך [ ] דורש כי שמו הפרטי של הסופר הוא Rick. שאלה: כתבו ביטוי המחזיר את כל הספרים מהמילניום הנוכחי? /bib/book[ year >= 2000] על מנת לבצע את השוואה, הערך הטקסטואלי של צומת year מומר לערך מספרי. בתוך הסוגריים המרובעות ניתן לשים ביטויי xpath כאשר נקודת המוצא היא הצומת מחוץ לסוגריים שאותה בודקים כרגע. צומת ההקשר. 2. הביטוי יוצא אמת אם הביטוי נכון עבור לפחות אחד מהצמתים שנבחרים בביטוי ה-xpath שבתוך הסוגריים. (דוגמא שימושית: מה אם לRick יש שם פרטי נוסף? ) 3. בביטויים שמכילים טקסט נעשת המרה אוטומטית לטקסט. תוספת שלי לא מהספסיפקציות: ניתן גם להמיר צמתים שלמים עם הבנים שלהם לטקסט ע"י השטחת הכל לטקסט. במקרה זה יש חשיבות ל-white space מכל סוג ובתנאי שהוא בתוך צומת טקסט. משום כך השטחה של ה-author תתקבל כ-“RichHull” זה מפני ש-enter והרווחים שמחוץ לצמתי הטקסט אינם נלקחים בחשבון. Spring 2005
בחירה לפי ביטויים בוליאניים //book[@price<60][publisher = "Addison-Wesley"] המשמעות של […][…] היא קיום הביטוי הראשון. מהרשומות שקיבלנו לאחר קיום הביטוי הראשון נדרוש גם קיום הביטוי השני. התוצאה ? הביטוי הנ"ל שקול ל- //book[@price<60 and publisher = "Addison-Wesley"] (כפי שנראה בהמשך השקילות לא קיימת כאשר התנאי תלוי בקבוצת הייחוס) Spring 2005
ביטויים בוליאניים קיומיים (existential) /bib/book/author[first-name][address[zip][city]]/last-name התוצאה: מוחזרים שמות משפחה (last-name) של סופרים בעלי שם פרטי המופיע בתוך צומת נפרד ובעלי כתובת הכוללת מיקוד (zip) ושם עיר (city). המשמעות של [first-name] היא הדרישה כי לכל צומת author יש לפחות צומת בן first-name אחד. שאלה: החזירו סופרים בעלי שם פרטי בלבד (ללא שם משפחה). /bib/book/author[first-name][not(last-name)] Spring 2005
פונקציות /bib/book[2] שקול ל- /bib/book[position() = 2] //author[last()] פונקציה last() מחזירה את מיקום הצומת האחרון בקבוצת הייחוס. האם שני הביטויים הבאים שקולים? //author[1][2] //author[2][1] לגבי השאלה האחרונה. דבר ראשון נראה שזה תמיד מחזיר כלום כי יש כביכול פעולת and בין הסוגריים. קבוצת הייחוס של צומת היא הקבוצה שמכילה אותו שנוצרה כתוצאה מהחיפוש האחרון בשרשרת החיפוש. לדוגמא כאן רשום //author שזה אומר תמצא את כל הצמתים במסמך(/descendant-or-self::node()/). אח"כ לכל צומת כזה תמצא את הבנים שלו (child::) שהם author. לכן הקבוצה שנוצרה כתוצאה מהחיפוש האחרון ומכילה את הצומת היא קבוצת כל הבנים מסוג author של הצומת שהיא אבא שלו. בסוגריים הראשונים ה-position() מחושב מתוך קבוצת הייחוס שלו – כלומר כל ה-author שהם בנים של אבא שלו. כלומר author[2] בוחר כל author שהוא ה-author השני תחת אותו אב. לאחר מכן כשמגיעים לסוגריים השניים קבוצת הייחוס היא התוצאה של החיפוש האחרון כלומר לאחר שנעשתה הבחירה של הסוגריים הראשונים. הסוגרים הראשונים בחרו מיקום ספציפי ברשימה ולכן התוצר הוא צומת בודד ולכן [2] לא יהיה קיים בעוד ש-[1] כן יהיה קיים. משום כך author[1][1] ו-author[2][1] יחזירו ערכים בעוד ש-author[1][2] ו-author[2][2] לא יחזירו ערכים. לעומת זאת אם נרשום author[position()>=2][2] אז הבחירה בסוגריים הראשונות תבחר לנו את כל ה-author שהם במקום השני או יותר. אם יש צומת שלה שלוש או יותר בנים שהם author אזי הסוגריים הראשונות יחזירו רשימה עם לפחות שני צמתים ואז הסוגריים השניים יחזירו את הערך השני הזה. לתת דוגמא Spring 2005
פונקציות – דוגמא לשאלת שקילות נסתכל על הערכים שיוחזרו בדוגמא עבור מסמך הדוגמא הערכים שיוחזרו עבור //author[1] – הסופר הראשון בכל ספר <author>Serge Abiteboul</author> <author>Jeffery D. Ullman</author> //author[1][2] לא יחזיר ערכים, מכיוון שבכל צומת בקבוצת הצמתים שהוחזרו ישנו רק סופר אחד //author[2] שקול ל- //author[2][1] <author> <first-name>Rick</first-name> <last-name>Hull</last-name> </author> מכאן שהביטויים אינם שקולים Spring 2005
פונקציות - המשך /bib//*[name()=”book”] שקול ל- /bib//book /bib/book[count(author)>1] count() מחזירה את מספר הצמתים בקבוצת הקלט. id(“a0130353000”) id() מחזירה את הצמתים בעלי תכונות ID כפי שנתון ע"י הקלט. ומה אם רשום לי id(“a1 a2”)? (יחזיר את שניהם) Spring 2005
XPath – כיווני ניווט (צירים – axes) ניתן לנוע על פני 13 הכיוונים הבאים: ancestor:: - מכיל אבות קדמונים של צומת ההקשר ancestor-or-self:: - מכיל אבות קדמונים של צומת ההקשר ואת הצומת עצמו attribute:: - מכיל אטריביוטים (תכונות) של צומת ההקשר child:: - מכיל בנים של צומת ההקשר descendant:: - מכיל צאצאים של צומת ההקשר descendant-or-self:: - מכיל צאצאים של צומת ההקשר following:: - מכיל צמתים המופיעים אחרי צומת ההקשר במסמך למעט צמתים צאצאים Following:: - כל הצמתים אחרי צומת ההקשר. הצאצאים של צומת ההקשר לא נכללים. Spring 2005
כיווני ניווט - המשך following-sibling:: - מכיל אחים של צומת ההקשר המופיעים אחריו במסמך namespace:: - מכיל צמתים מסוג namespace של צומת ההקשר parent:: - מכיל את צומת האב (אם קיים) של צומת ההקשר preceding:: - מכיל צמתים המופיעים לפני צומת ההקשר במסמך למעט צמתים שהם אבות קדמונים preceding-sibling:: - מכיל אחים של צומת ההקשר המופיעים לפניו במסמך self:: - מכיל את צומת ההקשר עצמו preceding – מכיל את הצמתים לפני הצומת. לא מכיל את צמת האבות. כלומר מכיל את כל האחים שלפניו. ואת כל האחים של אבא שלו שלפני אבא שלו (אבל לא את אבא שלו) ואת הצאצאים של האחים האלו והאחים של הסבא וכו'.... Spring 2005
קיצורים כתיב מקוצר כתיב מלא ברירת מחדל child:: @ attribute:: . self::node() כתיב מקוצר כתיב מלא ברירת מחדל child:: @ attribute:: . self::node() .. parent::node() כתיב מקוצר כתיב מלא ברירת מחדל child:: @ attribute:: . self::node() .. parent::node() // /descendant-or-self::node()/ [number] [position() = number] כתיב מקוצר כתיב מלא ברירת מחדל child:: @ attribute:: . self::node() .. parent::node() // /descendant-or-self::node()/ לשים דגש על ההבדל בין self::node() לבין self::. כגון /bib/self::bib יחזיר לי את הצומת הראשונה /bib. לעומת זאת /bib/./bib יחזיר לי /bib/bib. Spring 2005
קיצורים- דוגמאות כתיב מקוצר כתיב מלא /bib/book /child::bib/child::book /bib/book/@price /child::bib/child::book/ attribute::price כתיב מקוצר כתיב מלא /bib/book /child::bib/child::book /bib/book/@price /child::bib/child::book/ attribute::price /.//title (equivalent to //title) /self::node()/descendant-or-self::node()/child::title //author/.. /descendant-or-self::node()/ child::author/parent::node() כתיב מקוצר כתיב מלא /bib/book /child::bib/child::book /bib/book/@price /child::bib/child::book/ attribute::price /.//title (equivalent to //title) /self::node()/descendant-or-self::node()/child::title Spring 2005
דוגמאות מה מחזירים הביטויים הבאים? //book/publisher/parent::*/author //author/descendant-or-self::node()/child::zip ⇔ //author//zip ⇔ //author/descendant::zip מה מחזירים הביטויים הבאים? //book/publisher/parent::*/author //book[author[position()<last()]] //book[count(author[1]) = count(author[1] | author[last()] ) ] שני הביטויים עלולים להחזיר תוצאות שונות אם מוסיפים בסוף בחירת מיקום בחירת מיקום הכוונה לשימוש ב-position(). לתת דוגמא שמסבירה על קבוצות ייחוס. אלא אם כן זה ברור כבר כי הזכרתי את זה בשקף של הפונקציות. הדוגמאות למטה: דוגמא 1: כל המחברים של ספרים שיש להם מוציא לאור דוגמא 2: כל הספרים שיש להם יותר ממחבר אחד. להדגיש שקבוצת הייחוס של author הוא כל המחברים תחת book מסויים. דוגמא 3: כל הספרים שיש להם לכל היותר מחבר אחד. Spring 2005
דוגמאות - המשך מהם הספרים ששנת ההוצאה שלהם היא המאוחרת ביותר? //book[ not(year < //book/year) ] מי הם המחברים אשר כתבו יותר מספר אחד? יש להחזיר כל מחבר כזה פעם אחת בדיוק. /bib/book/author[.=../following-sibling::*/author and not(.=../preceding-sibling::*/author)] להוסיף איזשהי דוגמא אשר מסוג //a[b[@id = @ref]] כדי להראות שגם id וגם ref הם יחסית ל-b ובעצם לא ניתן לגשת לתכונות של a. Spring 2005
שאלה ממבחן <!ELEMENT tournament (game*)> <!ELEMENT game (GID, date, player, player, move*)> <!ELEMENT player (name, country, color)> <!ELEMENT move(no, status, piece, from, to)> <!ELEMENT piece(type, color)> כדי לפשט את הצגת ה-DTD, הניחו כי האלמנטים GID, date, name, country, color, no, status, from, to, type הם מסוג PCDATA. כתבו שאילתת XPath המוצאת את שם השחקן שביצע הזזת כלי במהלך מספר 7 של משחק מספר 99. על השאילתה למצוא את השחקן על ידי השוואת הצבע שבו הוא משחק לצבע הכלי שהוזז במהלך הנדון. Spring 2005
שאלה ממבחן - פתרון משחק מספר 99 //game[GID=99] הצבע של מהלך מספר 7 במשחק 99 //game[GID=99]/move[no=7]/piece/color שם השחקן שביצע את הזזת הכלי במהלך מספר 7 במשחק 99 //game[GID=99]/player[color = ../move[no=7]/piece/color]/name Spring 2005