Муқаддима Салом ба ҳама хонандагони мақолаи охирини ман ва ман мехоҳам шуморо табрик намоям: чизҳои мураккаб дар бораи XML пушти сари мост. Ин мақола дорои code дар Java хоҳад буд. Як каме назария ва баъд амалия мешавад. Аз сабаби он, ки як порчаи мавод дар SAX 10 саҳифаро дар Word пур кардааст, ман фаҳмидам, ки ман ба маҳдудиятҳо мувофиқат карда наметавонам. Аз ин ру, моддаи 3 ба 3 моддаи алохида таксим карда мешавад, сарфи назар аз он ки он чи кадар ачибе бошад. Ҳама чиз бо ин тартиб хоҳад буд: SAX -> DOM -> JAXB. Ин мақола танҳо ба SAX тамаркуз хоҳад кард. PS Дар курс дар ҷое вазифае вуҷуд дошт, ки дар он бояд ҳамаи унсурҳои дохorро дар файли HTML намоиш диҳед. Пас аз ин мақола, шумо метавонед ин корро бидуни хондани сатр ба сатр бо
BufferedReader
алгоритмҳои коркарди анъанавӣ ва мураккаб иҷро кунед ва инчунин ҳалли шабеҳ дар мисоли охирини амалӣ дода мешавад. Биёед оғоз кунем :) SAX (Simple API for XML) - НАЗАРИЯ Коркарди SAX тавре тарҳрезӣ шудааст, ки он танҳо файлҳои XML-ро пайдарпай мехонад ва ба рӯйдодҳои гуногун вокуниш нишон медиҳад ва баъд аз он маълумотро ба коркардкунандаи рӯйдодҳои махсус медиҳад. Он дорои якчанд рӯйдодҳо мебошад, аммо бештар маъмул ва муфидтаринҳо инҳоянд:
startDocument
— ибтидои хуччатendDocument
- охири ҳуҷҷатstartElement
- кушодани элементendElement
- бастани элементcharacters
— иттилооти матнӣ дар дохor элементҳо.
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
Акнун, аввал, мо бояд як SAXParser эҷод кунем:
public class SAXExample {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
// Creation фабрики и образца parserа
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
}
}
Тавре ки шумо мебинед, шумо бояд аввал як корхона созед ва баъд худи parserро дар завод эҷод кунед. Акнун, ки мо худи таҳлилгар дорем, барои рӯйдодҳои он ба мо коркардкунанда лозим аст. Барои ин ба мо синфи алоҳида лозим аст, то ки бароҳатии мо бошад:
public class SAXExample {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
}
private static class XMLHandler extends DefaultHandler {
@Override
public void startDocument() throws SAXException {
// Тут будет логика реакции на начало documentа
}
@Override
public void endDocument() throws SAXException {
// Тут будет логика реакции на конец documentа
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// Тут будет логика реакции на начало element
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// Тут будет логика реакции на конец element
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// Тут будет логика реакции на текст между elementми
}
@Override
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
// Тут будет логика реакции на пустое пространство внутри элементов (пробелы, переносы строчек и так далее).
}
}
}
Мо синферо таъсис додем, ки бо тамоми усулҳое, ки барои коркарди рӯйдодҳое, ки дар назария номбар шудаанд, лозим буд. Каме бештар назарияи иловагӣ: Каме дар бораи characters
: агар элемент матн дошта бошад, масалан, " салом ", пас, аз ҷиҳати назариявӣ, методро барои ҳар як аломати алоҳида 5 маротиба дар як саф даъват кардан мумкин аст, аммо ин кори бузург нест, зеро ҳама чиз то ҳол кор хоҳад кард. Дар бораи startElement
ва усулҳо endElement
:uri
- ин фазоест, ки дар он элемент ҷойгир аст, localName
- ин номи элемент бе префикс аст, qName
- ин номи элемент бо префикс аст (агар вуҷуд дошта бошад, дар акси ҳол танҳо ном аз элемент). uri
ва localName
ҳамеша холӣ аст, агар мо коркарди фазоро дар корхона фаъол накарда бошем. Ин бо усули завод ба чо оварда мешавад setNamespaceAware(true)
. Он гоҳ мо метавонем фосила ( uri
) ва элементҳоеро, ки дар пешашон префикс доранд ( localName
) гирем. Вазифаи №1 - Мо XML-и зерин дорем
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<company>
<name>IT-Heaven</name>
<offices>
<office floor="1" room="1">
<employees>
<employee name="Maksim" job="Middle Software Developer" />
<employee name="Ivan" job="Junior Software Developer" />
<employee name="Franklin" job="Junior Software Developer" />
</employees>
</office>
<office floor="1" room="2">
<employees>
<employee name="Herald" job="Middle Software Developer" />
<employee name="Adam" job="Middle Software Developer" />
<employee name="Leroy" job="Junior Software Developer" />
</employees>
</office>
</offices>
</company>
Ҳадафи мо: гирифтани ҳама маълумот дар бораи ҳамаи кормандон аз ин файл. Аввалан, мо бояд як синф эҷод кунемEmployee
:
public class Employee {
private String name, job;
public Employee(String name, String job) {
this.name = name;
this.job = job;
}
public String getName() {
return name;
}
public String getJob() {
return job;
}
}
Ва дар синфи асосии мо SAXExample
ба мо рӯйхат бо ҳамаи кормандон лозим аст:
private static ArrayList<Employee> employees = new ArrayList<>();
Акнун биёед бодиққат бубинем, ки маълумоте, ки ба мо лозим аст, дар файли XML куҷост. Ва, тавре ки мо мебинем, ҳама маълумоте, ки ба мо лозим аст, атрибутҳои элементҳо мебошанд employee
. Ва азбаски startElement
мо чунин як параметри муфид дорем attributes
, пас мо вазифаи хеле содда дорем. Аввалан, биёед усулҳои нолозимро хориҷ кунем, то codeи моро вайрон накунем. Ба мо танҳо лозим аст startElement
. Ва дар худи усул, мо бояд маълумотро аз атрибутҳои теги корманд ҷамъ кунем. Диққат:
public class SAXExample {
private static ArrayList<Employee> employees = new ArrayList<>();
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
}
private static class XMLHandler extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equals("employee")) {
String name = attributes.getValue("name");
String job = attributes.getValue("job");
employees.add(new Employee(name, job));
}
}
}
}
Мантиқ оддӣ аст: агар номи элемент бошад employee
, мо танҳо дар бораи атрибутҳои он маълумот мегирем. Усули муфид вуҷуд attributes
дорад, ки шумо метавонед номи атрибутро дониста, арзиши онро ба даст оред. Ин аст он чизе ки мо истифода бурдем. Ҳоло, ки мо коркардкунандаи рӯйдодҳоро барои оғози элемент офаридаем, мо бояд файли XML-и худро таҳлил кунем . Барои ин, танҳо ин корро кунед:
public class SAXExample {
private static ArrayList<Employee> employees = new ArrayList<>();
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLHandler handler = new XMLHandler();
parser.parse(new File("resource/xml_file1.xml"), handler);
for (Employee employee : employees)
System.out.println(String.format("Name сотрудника: %s, его должность: %s", employee.getName(), employee.getJob()));
}
private static class XMLHandler extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equals("employee")) {
String name = attributes.getValue("name");
String job = attributes.getValue("job");
employees.add(new Employee(name, job));
}
}
}
}
Дар усули таҳлил шумо бояд роҳро ба файли xml ва коркардкунандаи эҷодкардаатон гузаронед. Ҳамин тавр, бо истифода аз ин code мо аз ин XML маълумот гирифтем:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<company>
<name>IT-Heaven</name>
<offices>
<office floor="1" room="1">
<employees>
<employee name="Maksim" job="Middle Software Developer" />
<employee name="Ivan" job="Junior Software Developer" />
<employee name="Franklin" job="Junior Software Developer" />
</employees>
</office>
<office floor="1" room="2">
<employees>
<employee name="Herald" job="Middle Software Developer" />
<employee name="Adam" job="Middle Software Developer" />
<employee name="Leroy" job="Junior Software Developer" />
</employees>
</office>
</offices>
</company>
Ва мо натиҷаи зеринро гирифтем:
Name сотрудника: Maksim, его должность: Middle Software Developer
Name сотрудника: Ivan, его должность: Junior Software Developer
Name сотрудника: Franklin, его должность: Junior Software Developer
Name сотрудника: Herald, его должность: Middle Software Developer
Name сотрудника: Adam, его должность: Middle Software Developer
Name сотрудника: Leroy, его должность: Junior Software Developer
Миссия иҷро шуд! Вазифаи №2 - мо XML-и зерин дорем:
<?xml version="1.0" encoding="UTF-8"?>
<company>
<name>IT-Heaven</name>
<offices>
<office floor="1" room="1">
<employees>
<employee>
<name>Maksim</name>
<job>Middle Software Developer</job>
</employee>
<employee>
<name>Ivan</name>
<job>Junior Software Developer</job>
</employee>
<employee>
<name>Franklin</name>
<job>Junior Software Developer</job>
</employee>
</employees>
</office>
<office floor="1" room="2">
<employees>
<employee>
<name>Herald</name>
<job>Middle Software Developer</job>
</employee>
<employee>
<name>Adam</name>
<job>Middle Software Developer</job>
</employee>
<employee>
<name>Leroy</name>
<job>Junior Software Developer</job>
</employee>
</employees>
</office>
</offices>
</company>
Ҳадафи мо: гирифтани ҳама маълумот дар бораи ҳамаи кормандон аз ин файл. Ин мушкилот ба хубӣ нишон медиҳад, ки чӣ гуна файли XML-и суст сохташуда метавонад навиштани codeро душвортар кунад. Тавре ки шумо мебинед, маълумот дар бораи ном ва мавқеъ ҳоло ҳамчун иттилооти матнӣ дар дохor элементҳои name
ва нигоҳ дошта мешавад job
. Барои хондани матн дар дохor элементҳо, мо усули аломатҳоро дорем. Барои ин, мо бояд синфи нави коркардкунандаро бо мантиқи такмилёфта эҷод кунем. Фаромӯш накунед, ки коркардкунандагон синфҳои мукаммал мебошанд, ки қодиранд мантиқи ҳама гуна мураккабиро нигоҳ доранд. Аз ин рӯ, ҳоло мо протсессори худро танзим мекунем. Дарвоқеъ, қайд кардан кофӣ аст, ки мо ҳамеша навбат name
мегузорем job
ва муҳим нест, ки бо кадом тартиб, мо метавонем ном ва касбро ба осонӣ ба тағирёбандаҳои алоҳида захира кунем ва вақте ки ҳарду тағирёбанда захира карда мешаванд, корманди худро эҷод кунед. Танҳо дар ин ҷо, дар баробари оғози элемент, мо барои матн дар дохor элемент параметр надорем. Мо бояд усулҳоро дар матн истифода барем. Аммо чӣ гуна мо иттилооти матниро дар дохor элемент ба даст меорем, агар ин усулҳои тамоман гуногун бошанд? Ҳалли ман: мо бояд танҳо номи элементи охиринро дар хотир дошта бошем ва characters
тафтиш кунем, ки дар кадом элемент маълумотро мехонем. Шумо инчунин бояд дар хотир доред, ки аломатҳои <codee> ҳамаи аломатҳои дохor элементҳоро мехонанд, яъне ҳамаи фосилаҳо ва ҳатто танаффусҳои сатр хонда мешаванд. Ва мо ба онҳо ниёз надорем. Мо бояд ин маълумотро сарфи назар кунем, зеро он нодуруст аст.</codee> Code:
public class SAXExample {
private static ArrayList<Employee> employees = new ArrayList<>();
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
AdvancedXMLHandler handler = new AdvancedXMLHandler();
parser.parse(new File("resource/xml_file2.xml"), handler);
for (Employee employee : employees)
System.out.println(String.format("Name сотрудника: %s, его должность: %s", employee.getName(), employee.getJob()));
}
private static class AdvancedXMLHandler extends DefaultHandler {
private String name, job, lastElementName;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
lastElementName = qName;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String information = new String(ch, start, length);
information = information.replace("\n", "").trim();
if (!information.isEmpty()) {
if (lastElementName.equals("name"))
name = information;
if (lastElementName.equals("job"))
job = information;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ( (name != null && !name.isEmpty()) && (job != null && !job.isEmpty()) ) {
employees.add(new Employee(name, job));
name = null;
job = null;
}
}
}
}
Тавре ки шумо мебинед, аз сабаби мураккабии ғайриоддии сохтори файли XML, codeи мо ба таври назаррас мураккабтар шудааст. Бо вуҷуди ин, code мураккаб нест. Тавсиф: мо тағирёбандаҳоро барои нигоҳ доштани маълумот дар бораи корманд ( name
, job
) офаридем , инчунин як тағирёбанда lastElementName
барои сабти кадом элементе, ки мо дар дохor он ҳастем. Пас аз ин, дар усул characters
мо маълумотро филтр мекунем ва агар дар он ҷо ҳанӯз маълумот мавҷуд бошад, ин маънои онро дорад, ки ин матнест, ки ба мо лозим аст ва сипас бо истифода аз он муайян мекунем, ки ин ном ё касб аст lastElementName
. Дар усул endElement
, мо тафтиш мекунем, ки оё ҳама маълумот хонда шудааст ва агар ин тавр бошад, мо корманд эҷод мекунем ва маълумотро аз нав танзим мекунем. Натиҷаи маҳлул ба мисоли аввал баробар аст:
Name сотрудника: Maksim, его должность: Middle Software Developer
Name сотрудника: Ivan, его должность: Junior Software Developer
Name сотрудника: Franklin, его должность: Junior Software Developer
Name сотрудника: Herald, его должность: Middle Software Developer
Name сотрудника: Adam, его должность: Middle Software Developer
Name сотрудника: Leroy, его должность: Junior Software Developer
Ҳамин тариқ, ин мушкилот ҳал карда шуд , аммо шумо мебинед, ки мураккабӣ баландтар аст. Аз ин рӯ, мо метавонем хулоса барорем, ки нигоҳ доштани иттилооти матнӣ дар атрибутҳо нисбат ба унсурҳои алоҳида бештар дурусттар хоҳад буд. Ва боз як вазифаи ширине, ки мушкилотро дар JavaRush дар бораи намоиш додани маълумот дар бораи элемент дар HTML қисман ҳал мекунад, танҳо онро каме таҳрир кардан лозим аст, дар ин ҷо мо танҳо ҳамаи элементҳоро дар дохor элемент номбар мекунем :) Вазифаи №3 - бо назардошти унсури элемент, номҳо ва атрибутҳои ҳамаи унсурҳои дохorро нишон диҳед; агар элемент ёфт нашавад, онро нишон диҳед. Барои ин вазифа мо файли XML-ро истифода мебарем:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<oracle>
<connection value="jdbc:oracle:thin:@10.220.140.48:1521:test1" />
<user value="secretOracleUsername" />
<password value="111" />
</oracle>
<mysql>
<connection value="jdbc:mysql:thin:@10.220.140.48:1521:test1" />
<user value="secretMySQLUsername" />
<password value="222" />
</mysql>
</root>
Тавре ки шумо мебинед, мо дар ин ҷо се сенарияи имконпазир дорем: root
, mysql
, oracle
. Пас аз он, барнома тамоми маълумотро дар бораи ҳамаи унсурҳои дар дохor он нишон медиҳад. Мо инро чӣ тавр карда метавонем? Ва ин хеле содда аст: мо бояд танҳо як тағирёбандаи мантиқӣ эълон кунем isEntered
, ки нишон медиҳад, ки оё ба мо элемент дар дохor он лозим аст ва агар дар дохor он бошад, ҳама маълумотро аз startElement
. Рамзи ҳалли:
public class SAXExample {
private static boolean isFound;
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
SearchingXMLHandler handler = new SearchingXMLHandler("root");
parser.parse(new File("resource/xml_file3.xml"), handler);
if (!isFound)
System.out.println("Элемент не был найден.");
}
private static class SearchingXMLHandler extends DefaultHandler {
private String element;
private boolean isEntered;
public SearchingXMLHandler(String element) {
this.element = element;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (isEntered) {
System.out.println(String.format("Найден элемент <%s>, его атрибуты:", qName));
int length = attributes.getLength();
for(int i = 0; i < length; i++)
System.out.println(String.format("Name атрибута: %s, его meaning: %s", attributes.getQName(i), attributes.getValue(i)));
}
if (qName.equals(element)) {
isEntered = true;
isFound = true;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals(element))
isEntered = false;
}
}
}
Дар ин code ҳангоми ворид кардани элементе, ки дар бораи он ба мо маълумот лозим аст, мо парчамро isEntered
ба true муқаррар мекунем, яъне мо дар дохor элемент ҳастем. Ва ҳамин ки мо дар дохor элемент ҳастем, мо танҳо ҳар як унсури навро коркард мекунем startElement
ва медонем, ки он маҳз як унсури дохorи элементи мост. Ҳамин тавр, мо номи элемент ва унвони онро мебарорем. Агар элемент дар файл ёфт нашуда бошад, пас мо тағирёбанда дорем isFound
, ки ҳангоми пайдо шудани элемент муқаррар карда мешавад ва агар он нодуруст бошад, паёме нишон дода мешавад, ки элемент ёфт нашуд. Ва чунон ки шумо мебинед, дар мисол мо як элементро ба конструктор SearchingXMLHandler
гузаштем . root
Хулоса барои ӯ:
Найден элемент <oracle>, его атрибуты:
Найден элемент <connection>, его атрибуты:
Name атрибута: value, его meaning: jdbc:oracle:thin:@10.220.140.48:1521:test1
Найден элемент <user>, его атрибуты:
Name атрибута: value, его meaning: secretOracleUsername
Найден элемент <password>, его атрибуты:
Name атрибута: value, его meaning: 111
Найден элемент <mysql>, его атрибуты:
Найден элемент <connection>, его атрибуты:
Name атрибута: value, его meaning: jdbc:mysql:thin:@10.220.140.48:1521:test1
Найден элемент <user>, его атрибуты:
Name атрибута: value, его meaning: secretMySQLUsername
Найден элемент <password>, его атрибуты:
Name атрибута: value, его meaning: 222
Ҳамин тариқ, мо ҳама маълумотро дар бораи унсурҳои дохилӣ ва атрибутҳои онҳо гирифтем. Мушкилот ҳал шудааст. <h2>Эпилог</h2>Шумо дидед, ки SAX як абзори ҷолиб ва хеле муассир аст ва он метавонад бо тарзҳои гуногун, барои мақсадҳои гуногун ва ғайра истифода шавад, ба шумо танҳо лозим аст, ки ба мушкилот аз тарафи рост нигоҳ кунед. тараф, чи тавре ки дар супориши раками 2 ва 3 нишон дода шудааст, ки дар он чо САХ усулхои бевоситаи халли масъаларо пешбинй накардааст, вале ба шарофати заковати худ мо тавонистем, ки аз вазъият баромад кунем. Қисми навбатии мақола пурра ба DOM бахшида мешавад. Умедворам, ки шиносоӣ бо SAX ба шумо маъқул шуд. Таҷриба кунед, амал кунед ва шумо хоҳед фаҳмид, ки ҳама чиз хеле оддӣ аст. Ва ин ҳама, барори кор дар барномасозии шумо ва бесаброна интизори қисмат дар бораи DOM. Муваффақият дар таҳсил :) Мақолаи қаблӣ: [Мусобиқа] Асосҳои XML барои барномасози Java - Қисми 2 аз 3 Мақолаи навбатӣ: [Мусобиқа] Асосҳои XML барои барномасози Java - Қисми 3.2 аз 3 - DOM
GO TO FULL VERSION