450 likes | 628 Views
XPath. XML Path Language. מסמך דוגמא. < bib > < book price =“55”> < publisher >Addison-Wesley</ publisher > < author >Serge Abiteboul </ author > < author > < first-name >Rick</ first-name >
E N D
XPath XML Path Language
מסמך דוגמא <bib> <bookprice=“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> <!– this is a comment --> <publisher>Freeman</publisher> <author>Jeffrey D. Ullman</author> <title>Principles of Database and Knowledge Base Systems</title> <year>1998</year> </book> </bib>
מסמך XML כעץ צומת השורש bib צומת המסמך book book price=55 publisher author . . . . Addison-Wesley Serge Abiteboul
ביטויי XPath – דוגמאות פשוטות • /bib/book/year התוצאה: <year>1995</year> <year>1998</year> • /bib/paper/year התוצאה: קבוצה ריקה של צמתים (אין אלמנטים בעלי שם paper)
חיפוש צאצאים (סגור 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 התוצאה: <first-name>Rick</first-name> קבוצה של 4 צמתים
בחירת צמתים שאינם אלמנטים • text()מחזיר צמתים מסוג טקסט • node()מחזיר כל צמת ללא חשיבות לסוגו • comment()מחזיר צמתים מסוג הערה • מה יחזיר /bib/book/author/text()? • מחזיר את שמות הסופרים ששמם נמצא בצומת טקסט אחד. Serge Abiteboul Victor Vianu Jeffrey D. Ullman • הסופר Rick Hull אינו מופיע משום ששמו מופרד לשני אלמנטים, כלומר לאלמנט author לא קיים צומת בן מסוג טקסט. • מה יחזיר //comment()? • <!– this is a comment -->
בחירת אלמנט כלשהו - wildcard • //author/* התוצאה: <first-name>Rick</first-name> <last-name>Hull</last-name> ה-wildcard * במקרה זה בוחר כל צומת אלמנט ללא חשיבות לשמו.
גישה לתכונות • /bib/book/@price התוצאה: “55” ה-@ מתייחס לתכונות ה-@price מתייחס לתכונה price @*מתייחס לתכונה כל שהיא
השוואות • השוואות כלליות • =, =!, <, >, <=, >= • במקרה של השוואת בין סדרה לערך/סדרה ההשוואה תחזיר true אם קיים איבר אחד בסדרה שמקיים את היחס המבוקש • שני הביטויים בהשוואה חייבים להיות מאותו טיפוס
השוואות - המשך • השוואות סדר • <<, >>, is • השוואת המיקום היחסי של צמתים במסמך • שני הביטויים בהשוואה חייבים להיות מוערכים לערך בודד • השוואות כאלו חייבות להיות של צמתים בודדים, לא סדרות ולא ערכים שאינם צמתים
השוואות - המשך • הביטוי a>>b יחזיר trueאם"ם הצומת b מופיע במסמך אחרי הצומת a • בהתאמה >> ישמש לבדיקה שצומת מופיע לפני צומת אחר • לדוגמא: • //first-name = false<<//last-name • //first-name >>//last-name = true
השוואות - המשך • הביטוי a is b יחזיר trueאם"ם האלמנט b מופיע במסמך הוא בדיוק האלמנט a • אם a=b אך הם לא אותו אלמנט, יוחזר false • לדוגמא, אם נתון לנו צומת author אחר שמכיל: • <first-name>Israel</first-name> • <last-name>Israel</last-name> • (//first-name is //last-name) = false • (//first-name = //last-name) = true
בחירה לפי ביטויים בוליאניים • /bib/book/author[first-name = “Rick”] התוצאה: <author> <first-name>Rick</first-name> <last-name>Hull</last-name> </author> הביטוי בתוך [ ] דורש כי שמו הפרטי של הסופר הוא Rick.
בחירה לפי ביטויים בוליאניים • //book[@price<60][publisher = "Addison-Wesley"] המשמעות של[…][…]היא קיום הביטוי הראשון.מהרשומות שקיבלנו לאחר קיום הביטוי הראשון נדרוש גם קיום הביטוי השני. • הביטוי הנ"ל שקול ל- //book[@price<60 and publisher = "Addison-Wesley"] (כפי שנראה בהמשך השקילות לא קיימת כאשר התנאי תלוי בקבוצת הייחוס)
ביטויים בוליאניים קיומיים (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)]
פונקציות • /bib/book[2] • שקול ל- /bib/book[position() = 2] • פונקציה position() מחזירה את המספר הסידורי של צומת ההקשר בקבוצת הייחוס שלו. • //author[last()] • פונקציה last() מחזירה את מיקום הצומת האחרון בקבוצת הייחוס. • האם שני הביטויים הבאים שקולים? • //author[1][2] • //author[2][1]
פונקציות – דוגמא לשאלת שקילות • נסתכל על הערכים שיוחזרו בדוגמא עבור מסמך הדוגמא • הערכים שיוחזרו עבור //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> מכאן שהביטויים אינם שקולים
פונקציות - המשך • /bib//*[name()=”book”] • שקול ל- /bib//book • name() הינה פונקציה המחזירה את שם הצומת. • /bib/book[count(author)>1] • count() מחזירה את מספר הצמתים בקבוצת הקלט. • id(“a0130353000”) • id() מחזירה את הצמתים בעלי תכונות ID כפי שנתון ע"י הקלט. • מקבל מחרוזת בודדת כקלט • לא יקבל רצפים כקלט
פונקציות נוספות • distinct-values(set) • מחזירה את איברי הסדרה set ללא חזרות (עבור התוכן) • לא יישארו שני צמתים שונים שלהם אותו ערך מחרוזת • empty(set) • בודקת האם הסדרה set ריקה • reverse(set) • מחזירה את הסדרהset בסדר הפוך • index-of(set,val) • מחזירה את האינדקס של הערך val בסדרה set
XPath – כיווני ניווט (צירים – axes) • ניתן לנוע על פני 13 הכיוונים הבאים: • ancestor::- מכיל אבות קדמונים של צומת ההקשר • ancestor-or-self::- מכיל אבות קדמונים של צומת ההקשר ואת הצומת עצמו • attribute::- מכיל אטריביוטים (תכונות) של צומת ההקשר • child::- מכיל בנים של צומת ההקשר • descendant::- מכיל צאצאים של צומת ההקשר • descendant-or-self::-מכיל צאצאים של צומת ההקשר ואת הצומת עצמו • following::- מכיל צמתים המופיעים אחרי צומת ההקשר במסמך למעט צמתים צאצאים
כיווני ניווט - המשך • following-sibling::- מכיל אחים של צומת ההקשר המופיעים אחריו במסמך • namespace::- מכיל צמתים מסוג namespace של צומת ההקשר • parent::- מכיל את צומת האב (אם קיים) של צומת ההקשר • preceding::- מכיל צמתים המופיעים לפני צומת ההקשר במסמך למעט צמתים שהם אבות קדמונים • preceding-sibling::-מכיל אחים של צומת ההקשר המופיעים לפניו במסמך • self::- מכיל את צומת ההקשר עצמו
צירים הפוכים • ancestor-or-self, ancestor, parent,preceding,preceding-sibling • הופכים את סדר החיפוש במסמך • הסדר יכול להתהפך שוב • למשל בשימוש בסוגריים או בצירים שאינם הפוכים. • מה יחזיר //first-name/ancestor-or-self::node[1] • את צומת ה-first-name.
דוגמאות //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()] ) ] שני הביטויים עלולים להחזיר תוצאות שונות אם מוסיפים בסוף בחירת מיקום
דוגמאות - המשך • מהם הספרים ששנת ההוצאה שלהם היא המאוחרת ביותר? • //book[ not(number(year) <number(//book/year)) ] • מי הם המחברים אשר כתבו יותר מספר אחד? יש להחזיר כל מחבר כזה פעם אחת בדיוק. • /bib/book/author[.=../following-sibling::*/author and not(.=../preceding-sibling::*/author)]
פעולות על קבוצות • כל ביטוי XPath2.0 מחזיר סדרה של אלמנטים • ניתן להתייחס לכל סדרה כזו כקבוצת איברים • פעולות אפשריות: • איחוד – | • חיתוך – intersect • חיסור – except • ההמרה לקבוצה מוחקת כפילויות מהתוצאה
שרשור ביטויים • שרשור של ביטויים מאחד את סדרות התוצאה שלהם • שרשור מתבצע על "," • הביטוי //year,//authorיחזיר את כל אלמנטי ה-year במסמך ולאחריהם כל אלמנטי הauthor במסמך • חזרות לא יושמטו
רצפים • ביטוי XPath2.0 יכול ליצור רצף ערכים • הביטוי (1 to 5) יחזיר (1,2,3,4,5) • ניתן להשתמש ברצפים כאלה כחלק משאילתת Xpath • דוגמא בהמשך...
ביטויי בקרה • XPath2.0 מאפשרת שימוש במבני בקרה כחלק מהשאילתה • המבנים המותרים: • משתנים • תנאי if • לולאות for • כמתים
שימוש במשתנים • גישה למשתנה בשם var מתבצעת באמצעות הביטוי $var • הגדרת משתנה מתבצעת אוטומטית בעת שימוש בלולאת for או בכמתים • לא ניתן להגדיר משתנים או להציב לתוכם ערכים בדרך אחרת
תנאי if • If (expr1) then expr2 else expr3 • הביטוי expr1 משוערך לערך בוליאני • אם expr1 משוערך לtrue, מוחזר ערך הביטוי expr2 • אם expr1 משוערך לfalse, מוחזר ערך הביטוי expr3 • חובה לרשום ביטוי עבור הelse • ניתן להשתמש בסדרה ריקה ("()") כביטוי
תנאי if • מה יחזיר הביטוי הבא? //book[if (number(year)<2000) then count(author)>1 else count(author)<3] • תשובה: • כל הספרים שיצאו לפני שנת 2000 ויש להם יותר מכותב אחד או שיצאו החל משנת 2000 ויש להם פחות מ3 כותבים
תנאי if • ביטוי if שימושיים בעיקר בשילוב עם משתנים • אם המשתנה var מכיל אלמנט מטיפוס book: if (count($var/author)>=2) then $var/publisher else $var/title
לולאות for • for $var in expr1 return expr2 • הביטוי יחשב את expr2 עבור על אלמנט/ערך שיוחזר מexpr1 • תוצאת הביטוי היא שרשור כל התוצאות של expr2 • הביטוי expr2 יכול להשתמש במשתנה var
לולאות for • מה יחזיר הביטוי הבא: for $book in //book return $book/author • תשובה: • שקול ל-//book/author • במסמך הנוכחי, שקול ל-//author
לולאות for – דוגמא נוספת • מה תחזיר השאילתא הבאה: for $i in (1 to 100) return if (some $j in (2 to $i-1) satisfies $i mod $j = 0) then () else $i • את כל המספרים הראשוניים בין 1 ל-100.
הרכבת מבני בקרה • ניתן להרכיב ולשרשר מבני בקרה • לדוגמה: for $var in //book return if (count($var/author)>=2) then $var/publisher else $var/title • הביטוי יחזיר את כל המו"לים של ספרים שיש להם לפחות שני כותבים ואת הכותרות של שאר הספרים
כמת קיים • some $varin expr1 satisfies expr2 • הביטוי מחזיר true אם לפחות אחד מהערכים שמוחזרים מexpr1 מקיים את expr2 • שקול לביטוי not(empty(for $var in expr1 return if expr2 then $var else ()))
כמת קיים • מה יחזיר הביטוי הבא? distinct-values( //book/title[ some $bt in //books/title satisfies ($bt = . and not $bt is .) ] ) • תשובה: • הביטוי יחזיר את שמות כל הספרים שקיים עוד ספר עם אותו שם ללא כפילויות
כמת לכל • every $varin expr1 satisfies expr2 • הביטוי מחזיר true אם כל הערכים שמוחזרים מexpr1 מקיים את expr2 • שקול לביטוי empty(for $var in expr1 return if expr2 then () else $var)
כמת לכל • מה יחזיר הביטוי הבא? //book [ every $b in //books satisfies (title != $b/title) or number(year) >= number($b/year) ]/title • תשובה: • הביטוי יחזיר את שמות כל הספרים שלא קיים ספר אחר עם אותו שם שיצא בשנה מוקדמת יותר
שאלה ממבחן <!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. על השאילתה למצוא את השחקן על ידי השוואת הצבע שבו הוא משחק לצבע הכלי שהוזז במהלך הנדון.
שאלה ממבחן - פתרון • משחק מספר 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