If you are a developer 1C or write in PHP, or C++, it does not matter, but sooner or later you will be faced with XML. Why? Because it is universal, convenient, ubiquitous, cool, cross-platform . XML correctly understands in Android, Windows and Linux, etc. It is used for the exchange of information. It is used to store information.
In this post, I will explain how to read XML using 1C mechanism XDTO. You can see that the code is very simple, and no conversion is not required for XML values.
“Now, here, you see, it takes all the running you can do, to keep in the same place. If you want to get somewhere else, you must run at least twice as fast as that!”
Red Queen
Do not know why I put it here :).
With problem of the read / write XML I have encountered in connection with the integration of corporate websites of various companies with 1C, namely, customers want to exchange some information between 1C and their site, and do it with some frequency. Typically, these were sales (information for managers), orders (for dealers) and various data like log requests, tasks, reports, etc.
EXAMPLE I.
Let us suppose such a task, let the students are registered on the site of a certain educational institution (no matter what may be to get tested or something else). The manager wants to put the data in the 1C catalog “Students”. PHP programmer said “No problem!” and gave a XML file like this:
John Smith Male 1986-05-11 2 123
Here, the root element is the “students”. Subelement is “student”, which contains basic information about the student. Elements “name”, “last_name”, “sex”, “comment” are of type “string”, “birth” - “date”, “level” - “integer”. We need to read this data and write in the catalog “Students” of our infobase.
How to read? You can use the “XMLReader” , but then you will need to process a document line by line. And it is good if nesting levels only 2-3. But if they are 10 and 10 thousand lines? You can be processed using “DOMDocument” which creates us some tree representation of the document XML. But then we will need to process each item separately, you will need to write code to convert the element to correct type. It is not our method . Let’s try to create a XDTO-package and read by it our XML file. To do this, I created a new configuration with the following objects :
I created XDTO package “Students”:
And I defined a namespace “http: //localhost/xdto”. What is namespace? Check Wkipedia!
In this package I described the XML scheme. You can even right-click on the package and export the schema (file extension “.xsd”). For properties I also have types: name, last_name, sex, comment are of type “string” (http://www.w3.org/2001/XMLSchema). As you can see, the string type is also defined in some namespace, namely his determined together on conference w3 standard. The property “birth” has a date type (http: //www.w3.org/2001/XMLSchema), level - integer (http: //www.w3.org/2001/XMLSchema). How this is done you can look at example infobase (link at the end of this article).
Also you can define this schema this way:
The difference is only one, I created a type “type_student” and identified the type of “student” property. This is called explicit type definition. And before that was implicit type definition. And now let’s read XML and create elements in catalog. To do this, I created a data processor “XMLReading”, which can also look in example, here I give only the code:
&AtClient Procedure OneStudent(Commant) OneStudentServer(XML); EndProcedure &AtServerNoContext Procedure OneStudentServer(XML) // get XDTO type for students and read XML stType = XDTOFactory.Type("http://localhost/xdto", "students"); oReadXML = New XMLReader; oReadXML.SetString(XML); ObjectXDTO = XDTOFactory.ReadXML(oReadXML, stType); FirstStudent = ObjectXDTO.student; // Check if this student already exists in the database Query = New Query("SELECT | Students.Ref |FROM | Catalog.Students AS Students |WHERE | Students.FirstName LIKE ""%"" + &FirstName + ""%"" | AND Students.LastName LIKE ""%"" + &LastName + ""%"" | AND Students.BurthDate = &BurthDate"); Query.SetParameter("FirstName", FirstStudent.name); Query.SetParameter("LastName", FirstStudent.last_name); Query.SetParameter("BurthDate", FirstStudent.birth); Result = Query.Execute(); If Result.IsEmpty() Then objStudent = Catalogs.Students.CreateItem(); Else Selection = Result.Select(); While Selection.Next() Do objStudent = Selection.Ref.GetObject(); Break; EndDo; EndIf; // Fill attributes objStudent.FirstName = FirstStudent.name; objStudent.LastName = FirstStudent.last_name; objStudent.BurthDate = FirstStudent.birth; objStudent.Sex = FirstStudent.sex; objStudent.Level = FirstStudent.level; objStudent.Comment = FirstStudent.Comment; objStudent.Write(); EndProcedure
You can see that the code is very simple, and no conversion readed XML elements is not required, it does XDTOFactory. Well, let’s use our data processor and check whether there will be a new entry in the catalog “Students”. Error!
The fact that we do not specify XML namespaces.
Let’s take the XML, which I quoted above, and add:
John Smith Male 1986-05-11 2 123
EXAMPLE II
Let us assume that the XML contain not one student but several:
John Smith Male 1986-05-11 2 123 Brad Pitt Male 1960-01-11 3
If you try to read it with a scheme which we did, you get an error, and rightly so, we are not defined in the scheme that there may be many students. Let’s fix this situation by modifying the property “student”:
Please note, that property “Maximum number” I changed to “-1”, it means that the property “student” able contain unlimited number. If we set this property to “3”, the count of “student” can not be more than 3, etc.
Launch data processor and everything works!
Here the modified code. Of course, it is strongly not recommended to put a query in the cycle, but I do not want to do some optimization:
&AtClient Procedure ReadManyStudents(Command) ReadManyStudentsAtServer(); EndProcedure &AtServer Procedure ReadManyStudentsAtServer() // get XDTO type for students and read XML stType = XDTOFactory.Type("http://localhost/xdto", "students"); oReadXML = New XMLReader; oReadXML.SetString(XML); ObjectXDTO = XDTOFactory.ReadXML(oReadXML, stType); For Each FirstStudent In ObjectXDTO.student Do // Check if this student already exists in the database Query = New Query("SELECT | Students.Ref |FROM | Catalog.Students AS Students |WHERE | Students.FirstName LIKE ""%"" + &FirstName + ""%"" | AND Students.LastName LIKE ""%"" + &LastName + ""%"" | AND Students.BurthDate = &BurthDate"); Query.SetParameter("FirstName", FirstStudent.name); Query.SetParameter("LastName", FirstStudent.last_name); Query.SetParameter("BurthDate", FirstStudent.birth); Result = Query.Execute(); If Result.IsEmpty() Then objStudent = Catalogs.Students.CreateItem(); Else Selection = Result.Select(); While Selection.Next() Do objStudent = Selection.Ref.GetObject(); Break; EndDo; EndIf; // Fill attributes objStudent.FirstName = FirstStudent.name; objStudent.LastName = FirstStudent.last_name; objStudent.BurthDate = FirstStudent.birth; objStudent.Sex = FirstStudent.sex; objStudent.Level = FirstStudent.level; objStudent.Comment = FirstStudent.Comment; objStudent.Write(); EndDo; EndProcedure
EXAMPLE III
Suppose we have XML, where there is no information on students (this case also happen sometimes). The XML text below:
Try to read it by our data processor. What is gained? Error!
And it is correct! We are specified in the factory that elements students can be from one to infinity. And here we have zero, so it is mistake. Let’s fix this moment:
I did the minimum number is zero and a maximum number -1, ie unlimited. Now everything is working properly.
EXAMPLE IV
All! We have provided all cases! You can go to drink tea…;). But then we get another XML:
John Smith Male 1986-05-11 2 123 !! Brad Pitt Male 1960-01-11 3 !!
Insert XML in a text box, click “Read many students.” What we get? The error!
And why error? Look at the XML. There is a new element “new_field”, which is not included in our factory. What to do? You can include it in our scheme, but what if the file will come again with another element XML? This case can be processed in the following way - open in a factory “type_student” property and set “Open” = “Yes”:
Well that’s all. Now you can read XML without any problems. Now tag “student” may contain besides given any other tags and they will be read as a string type. Link to example of this information base below the publication.