Przetwarzanie pliku WMRODZ.xml
Plik WMRODZ.xml zawiera wykaz rodzajów miejscowości i ich symbole.
Na stronie Opis struktury zbioru WMRODZ
możemy zapoznać się ze strukturą tego pliku, która przedstawiona jest poniżej
wg stanu na dzień 2018-03-01:
- • Opis struktury zbioru WMRODZ
- RM - symbol rodzaju miejscowości - 2 zn. C
- NAZWA_RM - nazwa rodzaju miejscowości -
24100 zn. C - STAN_NA - data danych w formacie RRRR-MM-DD - 10 zn. C
- • Symbole i nazwy rodzajów miejscowości:
- 00 - część miejscowości
- 01 - wieś
- 02 - kolonia
- 03 - przysiółek
- 04 - osada
- 05 - osada leśna
- 06 - osiedle
- 07 - schronisko turystyczne
- 95 - dzielnica
m. st. Warszawy - 96 - miasto
- 98 - delegatura
- 99 - część miasta
Gdybyśmy porównali strukturę pliku WMRODZ.xml z dnia 2013-02-28 ze strukturą pliku aktualnego, to zaszły pewne zmiany. Chyba symbol rodzaju miejscowości RM = 95 zmienił brzmienie z błędnie wpisanej „dzielnica m.⇓st. Warszawy” zamiast ' m.st. ' na pojedyncze określenie: dzielnica. Piszę „chyba zmienił brzmienie”, gdyż na stronie Ogólna charakterystyka systemów rejestru zakładka SIMC/SYSTEM IDENTYFIKATORÓW I NAZW MIEJSCOWOŚCI (SIMC), możemy przeczytać:
- Obecnie w katalogu miejscowości funkcjonuje 12 określeń rodzajowych, którym nadano dwucyfrowe symbole:
- 00 część miejscowości
- ...
- dzielnica m.⇓st. Warszawy (tutaj jednak ze spacją)
- ...
- 99 część miasta
Struktura pliku WMRODZ.xml
Poniżej struktura starego pliku WMRODZ.xml z dnia 2013-02-28 i struktura aktualnego pliku WMRODZ.xml.
Ponieważ struktura pliku WMRODZ.xml została zmieniona, funkcja przetwarzający plik WMRODZ.xml
musiała zostać dostosowana do obowiązującej struktury pliku (nazw zmienionych elementów) przetwarzanego pliku WMRODZ.xml.
Rozmiar elementu [NAZWA_RM] (nazwa rodzaju miejscowości) został zwiększony z 24 znaków do 100 znaków,
należy więc w tabeli tblWMRodz, zmienić rozmiar pola tNazwa_RM
z 24 znaków na 100 znaków.
<?xml version="1.0" encoding="UTF-8"?> <teryt> <catalog name="SIMC" type="all" date="2013-02-28"> <row> <col name="RM">01</col> <col name="NAZWA_RM">wieś</col> <col name="STAN_NA">2013-02-28</col> </row> <row> <col name="RM">02</col> <col name="NAZWA_RM">kolonia</col> <col name="STAN_NA">2013-02-28</col> </row> <row> <col name="RM">03</col> <col name="NAZWA_RM">przysiółek</col> <col name="STAN_NA">2013-02-28</col> </row> <row> <col name="RM">04</col> <col name="NAZWA_RM">osada</col> <col name="STAN_NA">2013-02-28</col> </row> <row> <col name="RM">05</col> <col name="NAZWA_RM">osada leśna</col> <col name="STAN_NA">2013-02-28</col> </row> <row> <col name="RM">06</col> <col name="NAZWA_RM">osiedle</col> <col name="STAN_NA">2013-02-28</col> </row> <row> <col name="RM">07</col> <col name="NAZWA_RM">schronisko turystyczne </col> <col name="STAN_NA">2013-02-28</col> </row> <row> <col name="RM">95</col> <col name="NAZWA_RM">dzielnica m. st. Warszawy</col> <col name="STAN_NA">2013-02-28</col> </row> <row> <col name="RM">96</col> <col name="NAZWA_RM">miasto</col> <col name="STAN_NA">2013-02-28</col> </row> <row> <col name="RM">98</col> <col name="NAZWA_RM">delegatura</col> <col name="STAN_NA">2013-02-28</col> </row> <row> <col name="RM">99</col> <col name="NAZWA_RM">część miasta</col> <col name="STAN_NA">2013-02-28</col> </row> <row> <col name="RM">00</col> <col name="NAZWA_RM">część miejscowości</col> <col name="STAN_NA">2013-02-28</col> </row> </catalog> </teryt>
<?xml version="1.0" encoding="utf-8"?> <SIMC> <catalog name="SIMC" type="ALL" date="2013-02-28"> <row> <RM>00</RM> <NAZWA_RM>część</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> <row> <RM>01</RM> <NAZWA_RM>wieś</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> <row> <RM>02</RM> <NAZWA_RM>kolonia</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> <row> <RM>03</RM> <NAZWA_RM>przysiółek</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> <row> <RM>04</RM> <NAZWA_RM>osada</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> <row> <RM>05</RM> <NAZWA_RM>osada leśna</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> <row> <RM>06</RM> <NAZWA_RM>osiedle</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> <row> <RM>07</RM> <NAZWA_RM>schronisko turystyczne</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> <row> <RM>95</RM> <NAZWA_RM>dzielnica</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> <row> <RM>96</RM> <NAZWA_RM>miasto</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> <row> <RM>98</RM> <NAZWA_RM>delegatura</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> <row> <RM>99</RM> <NAZWA_RM>część miasta</NAZWA_RM> <STAN_NA>2013-02-28</STAN_NA> </row> </catalog> </SIMC>
Struktura tabeli tblWMRodz.
Znając strukturę zbioru WMRODZ musimy utworzyć tabelę na przyjęcie danych z pliku WMRODZ.xml. Struktura tabeli przedstawiona jest poniżej:
Tabela tblWMRodz - struktura | |||||
Nazwa pola*) | Typ | Rozmiar**) | Wymagane | Zerowa długość | Uwagi |
ID_RM | Tekst | 2 | Tak | Nie | PrimaryKey |
tNazwa_RM | Tekst | Tak | Nie | ||
tStan_Na | Tekst | 10 | Tak | Nie |
Uwagi dodatkowe. Dotyczą wszystkich tabel na tej stronie. |
*) - Dla pola będącego kluczem głównym, stosuję prefiks „ID_”, - Klucz obcy zawsze poprzedzam prefiksem „Id_” - Nazwy pól nie będące kluczem głównym i kluczem obcym poprzedzam prefiksem „t” |
**) Minimalna długość pola. Można użyć większego rozmiaru pola. MS Access nie dopełnia pól tekstowych do zadeklarowanej długości. |
Tworzenie tabeli tblWMRodz.
Tabelę tblWMRodz możemy utworzyć korzystając z metod klasy clsTeryt opisanej na stronie: Klasa clsTeryt
Dim clsWMRodz As clsTeryt Set clsWMRodz = New clsTeryt With clsWMRodz .terytDeleteTable "tblWMRodz" .terytCreateTable "tblWMRodz" .terytCreateField "ID_RM", dbText, 2 .terytCreateField "tNazwa_RM", dbText, 100 .terytCreateField "tStan_Na", dbText, 10 .terytAppendTable ' utwórz Indeks Primary .terytCreateIndex "ID_RM", True End With Set clsWMRodz = Nothing
Skoro mamy już tabelę, to musimy pobrać dane z pliku WMRODZ.xml i zapisać je do nowo utworzonej tabeli.
Jak to zrobić ? Po prostu korzystając z analizatora składni XML firmy Microsoft (MSXML)
napisać własną funkcję przetwarzającą plik WMRODZ.xml i zapisującą dane do tabeli. Ale najpierw kilka słów
o odwołaniu się do „parsera MSXML”.
Analizator składni XML firmy Microsoft (MSXML)
Plik WMRODZ.xml i pozostałe
Pliki pełne rejestru TERYT (*.xml)
przetwarzać będziemy za pomocą obiektu spełniającego funkcję analizatora składni XML firmy Microsoft (MSXML),
który można prościej określić mianem „parsera XML”.
Parser MSXML jest zawarty w pliku msxml6.dll, który jako zgodny z mechanizmem Automatyzacji
udostępnia interfejs, który umożliwia wykorzystanie Automatyzacji do komunikowania się z naszą bazą danych.
Interfejs ten nigdy nie jest widoczny w samej aplikacji - dostęp do niego
można uzyskać tylko w kodzie VBA, który łączy się z interfejsem i korzysta z udostępnianych zasobów.
Aby uzyskać dostęp do obiektów, metod i właściwości analizatora składni XML firmy Microsoft (MSXML)
możemy wykorzystać „wczesne wiązanie” (ang. early binding) lub „późne
wiązanie” (ang. late binding).
Wczesne wiązanie (ang. early binding) biblioteki Microsoft XML,v6.0.
W przypadku „wczesnego wiązania”musimy utworzyć odwołanie do biblioteki obiektów poprzez wybranie polecenia „Tools/References” w edytorze Visual Basic. W otwartym oknie dialogowym „References” należy znaleźć bibliotekę Microsoft XML,v6.0 i zaznaczyć pole wyboru.

Mając dodane odwołanie do biblioteki Microsoft XML,v6.0, możemy zadeklarować zmienną obiektową xmlDoc typu MSXML2.DOMDocument60 i przypisać utworzony egzemplarz obiektu klasy MSXML2.DOMDocument60 do zmiennej xmlDoc:
Dim xmlDoc As MSXML2.DOMDocument60
Set xmlDoc = New MSXML2.DOMDocument60
Późne wiązanie (ang. late binding) Microsoft XML,v6.0.
Jeżeli nie określimy odwołania („Reference”) do biblioteki Microsoft XML,v6.0, to aby odwołać się do tego obiektu musimy zadeklarować zmienną jako typ Object i wykorzystując instrukcję Set w połączeniu z metodą CreateObject, ustawić odwołanie zmiennej obiektowej na nowy egzemplarza obiektu bibliotecznego.
Dim xmlDoc As Object
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
W przypadku gdy nie ma określonego obiektu bibliotecznego na lokalnym komputerze wystąpi błąd wykonania:

Aktualizacja funkcji własnej fXmlWMRodzToTable(...)
W porównaniu do struktury pliku WMRODZ.xml z dnia 28 lutego 2013 roku nastąpiła zmiana struktury, a raczej nazw elementów struktury tego pliku (i chyba pozostałych plików). Po tych zmianach aktualizacji musi ulec również funkcja fXmlWMRodzToTable(...). Na szczęście został wyeliminowany błąd, pojawiający się przy próbie wczytania danych z pliku WMRODZ.xmldo tabeli. MS Access zgłasza błąd:

wynikający z błędnego zapisu elementu [NAZWA_RM] = 'dzielnica m.⇓st. Warszawy', W opisie struktury zbioru WMRODZ było: [NAZWA_RM] - nazwa rodzaju miejscowości - 24 zn. C, a w rzeczywistości element [NAZWA_RM] zawierał 25 znaków. Obecnie element [NAZWA_RM] powinien mieć wielkość 100 znaków, a symbol rodzaju miejscowości [RM] = 95 zmienił brzmienie na 'dzielnica'
' Funkcja ta jest nieaktualna. Patrz listing w następnym akapicie. Public Function fXmlWMRodzToTable_Old( _ ByVal sFileXmlPath As String, _ ByVal sTblName As String) As Boolean #If pbl_fEarly = True Then Dim xmlDoc As MSXML2.DOMDocument60 Dim oRM As MSXML2.IXMLDOMNodeList Dim oNAZWA_RM As MSXML2.IXMLDOMNodeList Dim oSTAN_NA As MSXML2.IXMLDOMNodeList Dim oNodes As MSXML2.IXMLDOMNodeList #Else Dim xmlDoc As Object Dim oRM As Object Dim oNAZWA_RM As Object Dim oSTAN_NA As Object Dim oNodes As Object #End If Dim sXPath As String Dim i As Integer Const cParser_XML As String = "MSXML2.DOMDocument" Dim dbs As DAO.Database Dim rstRM As DAO.Recordset Const cModule_Name As String = "Function fXmlWMRodzToTable_Old (...)" On Error GoTo Err_Handler ' Utwórz obiekt analizatora składni XML (parsera XML) #If pbl_fEarly = True Then ' Wczesne wiązanie (early binding) Set xmlDoc = New MSXML2.DOMDocument60 #Else ' Późne wiązanie (late binding) Set xmlDoc = CreateObject("MSXML2.DOMDocument") #End If With xmlDoc .Load (sFileXmlPath) ' poprawka na zbyt długi (25 znakowy) element NAZWA_RM = "dzielnica m. st. Warszawy" ' pobierz .xml jako ciąg znaków, zastąp w nim pierwsze wystąpienie ciągu: " m. st. " ' na " m.st. " i ponownie załaduj metodą .loadXML obiektu "MSXML2.DOMDocument" ' Uwaga. Ważna jest wielkość liter ! .loadXML Replace(.xml, " m. st. ", " m.st. ", 1, 1, vbBinaryCompare) ' sprawdź poprawność wczytanego XML'a If (.parseError.errorCode <> 0) Then Err.Raise xmlDoc.parseError.errorCode, cParser_XML, xmlDoc.parseError.reason End If ' utwórz adres do elementu <row> sXPath = "/teryt/catalog/row" ' ustaw zmienną obiektową odnoszącą się do elementów <col> o nazwie: "RM" Set oRM = .SelectNodes(sXPath & "/col[@name='RM']") ' ustaw zmienną obiektową odnoszącą się do elementów <col> o nazwie: "NAZWA_RM" Set oNAZWA_RM = .SelectNodes(sXPath & "/col[@name='NAZWA_RM']") ' ustaw zmienną obiektową odnoszącą się do elementów <col> o nazwie: "STAN_NA" Set oSTAN_NA = .SelectNodes(sXPath & "/col[@name='STAN_NA']") ' ustaw zmienną obiektową odnosząca się do wszystkich elementów <row> Set oNodes = .SelectNodes(sXPath) End With ' utwórz zmienną obiektową do bieżącej bazy danych Set dbs = CurrentDb ' otwórz rekordset oparty na tabeli odnoszącej się do WMRODZ.xml Set rstRM = dbs.OpenRecordset(sTblName, dbOpenDynaset, dbAppendOnly) ' przejdź po wszystkich elementach <row> i zapisz wartości elementów <col> do tabeli For i = 0 To oNodes.length - 1 With rstRM .AddNew !ID_RM = oRM(i).Text !tNazwa_RM = oNAZWA_RM(i).Text !tStan_Na = oSTAN_NA(i).Text .Update End With Next fXmlWMRodzToTable_Old = True Exit_Here: ' zniszcz zmienne obiektowe If Not (rstRM Is Nothing) Then rstRM.Close Set rstRM = Nothing Set dbs = Nothing Set oRM = Nothing Set oNAZWA_RM = Nothing Set oSTAN_NA = Nothing Set oNodes = Nothing Set xmlDoc = Nothing Exit Function Err_Handler: MsgBox "Błąd nr " & Err.Number & vbNewLine & _ Err.Description & vbNewLine & _ "Źródło: " & Err.Source & vbNewLine & _ "Moduł: " & cModule_Name Resume Exit_Here End Function
Funkcja wczytująca dane z pliku WMRODZ.xml do tabeli MS Access
• Stan na dzień 03 marca 2018 roku
Public Function fXmlWMRodzToTable( _ ByVal sFileXmlPath As String, _ ByVal sTblName As String) As Boolean #If pbl_fEarly = True Then Dim xmlDoc As MSXML2.DOMDocument60 Dim oRM As MSXML2.IXMLDOMNodeList Dim oNAZWA_RM As MSXML2.IXMLDOMNodeList Dim oSTAN_NA As MSXML2.IXMLDOMNodeList Dim oNodes As MSXML2.IXMLDOMNodeList #Else Dim xmlDoc As Object Dim oRM As Object Dim oNAZWA_RM As Object Dim oSTAN_NA As Object Dim oNodes As Object #End If Dim sXPath As String Dim i As Integer Const cParser_XML As String = "MSXML2.DOMDocument" Dim dbs As DAO.Database Dim rstRM As DAO.Recordset Const cModule_Name As String = "Function fXmlWMRodzToTable (...)" On Error GoTo Err_Handler ' Utwórz obiekt analizatora składni XML (parsera XML) #If pbl_fEarly = True Then ' Wczesne wiązanie (early binding) Set xmlDoc = New MSXML2.DOMDocument60 #Else ' Późne wiązanie (late binding) Set xmlDoc = CreateObject("MSXML2.DOMDocument") #End If With xmlDoc .Load (sFileXmlPath) ' sprawdź poprawność wczytanego XML'a If (.parseError.errorCode <> 0) Then Err.Raise xmlDoc.parseError.errorCode, cParser_XML, xmlDoc.parseError.reason End If ' utwórz adres do elementu <row> sXPath = "/SIMC/catalog/row" ' ustaw zmienną obiektową odnoszącą się do elementów o nazwie: "RM" Set oRM = .selectNodes(sXPath & "/RM") ' ustaw zmienną obiektową odnoszącą się do elementów o nazwie: "NAZWA_RM" Set oNAZWA_RM = .selectNodes(sXPath & "/NAZWA_RM") ' ustaw zmienną obiektową odnoszącą się do elementów o nazwie: "STAN_NA" Set oSTAN_NA = .selectNodes(sXPath & "/STAN_NA") ' ustaw zmienną obiektową odnosząca się do wszystkich elementów <row> Set oNodes = .selectNodes(sXPath) End With ' utwórz zmienną obiektową do bieżącej bazy danych Set dbs = CurrentDb ' otwórz rekordset oparty na tabeli odnoszącej się do pliku WMRODZ.xml Set rstRM = dbs.OpenRecordset(sTblName, dbOpenDynaset, dbAppendOnly) ' przejdź po wszystkich elementach <row> i zapisz wartości poszczególnych elementów do tabeli For i = 0 To oNodes.Length - 1 With rstRM .AddNew !ID_RM = oRM(i).Text !tNazwa_RM = oNAZWA_RM(i).Text !tStan_Na = oSTAN_NA(i).Text .Update End With Next fXmlWMRodzToTable = True Exit_Here: ' zniszcz zmienne obiektowe If Not (rstRM Is Nothing) Then rstRM.Close Set rstRM = Nothing Set dbs = Nothing Set oRM = Nothing Set oNAZWA_RM = Nothing Set oSTAN_NA = Nothing Set oNodes = Nothing Set xmlDoc = Nothing Exit Function Err_Handler: MsgBox "Błąd nr " & Err.Number & vbNewLine & _ Err.Description & vbNewLine & _ "Źródło: " & Err.Source & vbNewLine & _ "Moduł: " & cModule_Name Resume Exit_Here End Function