ארכיון תגיות: XML

באגים ב-PHP בטיפול ב-XML באמצעות DomDocument \ SimpleXml

אני לא שותף למלחמות דת על "שפת התיכנות הטובה ביותר"

לרוב, מלחמות כאלו חסרות משמעות.

יחד עם זאת, הציפיה שלי משפת תיכנות, היא שהפקודות בה יעבדו כמו שצריך, בלי שאצטרך למצוא דרכים עוקפות כיוון שפקודה מסוימת לא עובדת בכל מצב.

כבר כמה שנים שאני מתעסק עם קבצי XML ענקים שמגיעים מגופים גדולים.

והסתבר לי עם הזמן שלספריות ש-PHP מציעה כדי לפענח XML, יש חסרונות עצומים.

  • אם הקובץ לא מגיע בקידוד המצופה ( למשל, הקובץ מוצהר כ-UTF-8 אבל בפועל הוא UTF-16LE )
    אז צריך לאתר זאת מראש, כי הפקודות שטוענות את הקובץ ומפרשות את ה-XML, לא יודעות לפענח את הקידוד השונה בעצמן.
  • שאילתות XPATH, לעיתים לא עובדות – מאוד תלוי "במצב הרוח" של הספריה.
    לדוגמא – DomDocument מסוגלת לבצע שאילתות XPATH בצורה טובה, ואז בלי סיבה מיוחדת – לא לעבוד.
  • לעיתים, ספריה אחרת יודעת לפרש את ה-XML, והספריה השניה לא מצליחה להתמודד איתו, ומחזירה false.

הפתרון שמצאתי בסופו של דבר קורא את הקובץ בספריה אחת ושומר אותו מחדש כדי שהספריה השניה תואיל בטובה לקרוא אותו בכל מצב.

זה אומנם עובד, אך גובה מחיר יקר בזמן עיבוד שבמקרה שלי הוא אקוטי כיוון שהלקוח יושב וממתין…

המצב הזה הוא ממש גרוע. ולצערי במקרה הזה – כל קובץ שהייתי צריך לבצע מניפולציות עליו ב-PHP, כאשר ניסיתי לפרש אותו עם VB , בספריה עתיקה ביותר של מיקרוסופט (MSXML 6 )  – זה הצליח תמיד , הרבה יותר מהיר, וללא שום בעיות.

במקרה הזה, יש לי רק מחמאות למיקרוסופט, הספריה העתיקה שלהם, עובדת מעולה.

מצבים כאלו, יוצרים תיסכול, כיוון שאילו זו הייתה ספריה אחת מתוך כמה – אז הייתי משתמש באחרות. אבל ב-PHP, נוצר מצב ש-2 הספריות העיקריות לא עושות את העבודה. ברוב הקבצים – ברור ששתיהן עובדות כמו שצריך.  אבל כשמגיעים קבצים עם קידוד בעייתי ועוד…כל ספריה מתנהגת בצורה בלתי צפויה בפקודות שלה.

מה המסקנה ?

אז אומנם php היא שפה מאוד כייפית לפיתוח, ומכילה כמות עצומה של פקודות וספריות, קהילה תומכת וכו' וכו'

אבל כנראה שיש צדדים מסויימים שבהם יש לה חסרונות ולגביהם כנראה צריך לבחור דרך להתגבר עליהם בשפות אחרות.

חבל …אבל זה מה יש.

אם יש לכם קבצי xml שאתם הייצרנים שלהם , ו- php היא שפת הפיתוח שלכם, אז תישארו איתה. אבל כשיש קבצי xml שאתם לא שולטים במקור שלהם, ויש סיכוי לקבצים עם בעיות …תבחרו שפה אחרת כדי לקרוא אותם. זו ההמלצה שלי.

בניה/יצירה של XML פשוט ב-MSXML (VBA)

ככה יוצרים אוביקט XML פשוט ב-MSXML
הדוגמא היא ב-VBA

הדוגמא יוצרת
1. מסמך
2. root node – כלומר הענף המרכזי של העץ
3. ענף "בן" אחד
4. מאפיין/attritube עבור ה-root node

בסוף היא מחזירה את ה-XML, אבל אם רוצים לשמור צריך להשתמש במתודה SAVE.


  Dim mydata As Object, pi As Object
  Dim Node As Object, Child As Object, att As Object
   'create an object, Late Binding
   Set mydata = CreateObject("Msxml2.DOMDocument.6.0")
   'create the first line, before the root element
   Set pi = mydata.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'")
   'now writes the the first line to the XML object
   mydata.InsertBefore pi, mydata.FirstChild
   
   'create root node
   Set Node = mydata.createElement("smart")
   'set attribute to the root node
    Node.setAttribute "goal", "login"
    'create child node
    Set Child = mydata.createElement("time")
    'set a text value to the child node
    Child.Text = Now
    'put the child under the first=root Node
    Node.appendchild Child
    'put the root node under the documnet object
   mydata.appendchild Node
   'return all the xml as string
   XMLobj = mydata.XML
End Function

פענוח פשוט של XML שמועבר ב-POST באמצעות simpleXML של PHP

ה-XML מועבר ב-POST
כאשר ההגדרה *במקור* ששלח את ה-XML היא כזו :

yourXMLobject.setRequestHeader "Content-type", "text/xml"

אז לכן משתמשים ב-raw post
כי – אין פה משתנים למעשה, אלא הכל XML אחד גדול.

זו הפונקציה

un . "
"; echo $xml->pw . "
"; // echo $xml_file; // echo $xml_post; } else { echo "it is not what you want";} ?>

איך לשלוח מידע ב-POST דרך msxml ( Late Binding

הדוגמא הבאה מראה שליחת מידע ב-POST דרך אוביקט xmsml
הדוגמא על VBA

יש לקחת בחשבון שצריך כמובן גם לפתח את הדף שמקבל את הנתונים שיחזיר תשובה כלשהיא – כדי לבדוק את הנתונים.

נקודה חשובה : במשלוח בפוסט, מחברים את הערכים באמצעות סימן &
כלומר

yourVariable=yourValue&anotherVariable=anotherValue

וזה הקוד VBA

Function PostXmlData(vUrl As String, xmlText As String)
Dim XMLHttp As Object
Set XMLHttp = CreateObject("MSXML2.XMLHTTP")

XMLHttp.Open "POST", vUrl, False
XMLHttp.setRequestHeader "Content-type", "application/x-www-form-urlencoded" 'charset=utf-8

XMLHttp.send (xmlText)

PostXmlData = XMLHttp.responseText
Debug.Print PostXmlData
End Function

התמודדות עם EntityRef: expecting ';' in Entity (מחרוזת XML שעוברת מ-MSXML אל PHP XML DOM )

יש לי מודול באחד התוכנות
שמשדר XML מתוך אקסל באמצעות MSXML גירסה 2 של MICROSOFT

אל Web Service ב-PHP

והשירות מחזיר XML בחזרה, כאשר ה-XML נשמר כרשומות בדאטאבייס.

עכשיו – מסתבר שלמרות שיש תקן מאוד ברור ל-XML

אז MSXML – לפעמים מתעלם ממנו.

היתה לי שורה שהכילה את מדד המניות האמריקאי – S&P

כמו שאתם רואים בין האותיות יש את סימן ה- &

אז ה-MSXML מכניס אותו למחרוזת בלי בעיה, למרות שזה לא תקין,

כי לפי ההגדרות – זהו סימן שמור שאמור להפוך לamp

זאת ההגדרה :

'&' (ampersand) becomes '&'

טוב… מה שקרה הוא כמובן תקלה, כי המרכיב ב-PHP שמקבל את זה , XML DOM (אוביקט DOMDocument )

לא ידע לאכול את זה….

הפתרון הוא ממש פשוט במקרה זה ,

רגע לפני שטוענים את ה-מחרוזת XML אל תוך האוביקט

צריך להפוך את הסימני & למשהו אחר.

ככה זה ב-php :

$tmp = str_replace('&','-',$tmp);

בהצלחה!

שמירת רשימת ערכים ממערך בתוך XML (פונקצית VBA )

הרבה פעמים אנחנו צריכים לשמור רשימה משתנה של ערכים.

בצורה של
מפתח = ערך
(key = value )

להלן פונקציה פשוטה שכתבתי שלוקחת מערך דו מימדי
כאשר בכל שורה יש 2 איברים
איבר מספר 1 – שם המאפיין
איבר מספר 2 – ערך המאפיין

הפונקציה מחזירה XML שמכיל את כל הערכים במערך

Public Function ArrayToXML(yAry As Variant) As String
    'This Function Get a 2 dimenesions array, and return XML string
    'On each row of the array need to be with 2 columns :
    '     1 - the name
    '     2 - the value
  Dim XmlObj As Object, pi As Object, I As Integer
  Dim Node As Object, Child As Object, att As Object
   'create an object, Late Binding
   Set XmlObj = CreateObject("Msxml2.DOMDocument.6.0")
   'create the first line, before the root element
   Set pi = XmlObj.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'")
   'now writes the the first line to the XML object
   XmlObj.InsertBefore pi, XmlObj.FirstChild
   'create root node
   Set Node = XmlObj.createelement("YourXmlRootNodeName")
        'Loop on the array
        For I = LBound(yAry, 1) To UBound(yAry, 1)
            'Create a Child node
             Set Child = XmlObj.createelement(yAry(I, 1))
            'Put the value
             Child.Text = yAry(I, 2)
            'put this Child node under the root node
            Node.appendchild Child
        Next I
    
    
    'put the root node under the documnet object
   XmlObj.appendchild Node
   'return all the xml as string
   ArrayToXML = XmlObj.xml
   
End Function

לולאה על ענפים של XML בפונקצית VBA

הפונקציה הבאה יכולה לשמש בסיס להרבה דברים

אם יש לך XML,

ואתה יודע לכתוב את שאילתת ה-XPATH הרצויה

אז בפונקצית VBA הבאה אתה מקבל את כל הענפים של השאילתא ששלחת.

כמובן שאת השורה באמצע הלולאה (שורת ה-Debug.Print ) תחליפו במה שנחוץ אצלכם


    Dim XmlObj As Object, XmlRoot As Object, XPathQuery As String, SingleNode As Object
    
     'îðúç àú äúùåáä
     Set XmlObj = CreateObject("Msxml2.DOMDocument.6.0")
     XmlObj.LoadXML XmlStr
     Set XmlRoot = XmlObj.DocumentElement
     
     XPathQuery = "//smart/*"
     Set xmlNodeList = XmlObj.SelectNodes(XPathQuery)
            
    For Each Node In xmlNodeList
        Debug.Print Node.nodename & " = " & Node.Text
     Next