XMLStats: aplicație web pentru analiza documentelor XML propusă de Cosmin -Alexandru Dochiței Sesiunea : Iulie, 2020 Coordonator științific Lect. Dr…. [607628]

1
UNIVERSITATEA “ALEXANDRU IOAN CUZA” DIN IA ȘI
FACULTATEA DE INFORMATICĂ

LUCRARE DE LICEN ȚĂ

XMLStats: aplicație web pentru analiza
documentelor XML

propusă de
Cosmin -Alexandru Dochiței

Sesiunea : Iulie, 2020
Coordonator științific
Lect. Dr. Ionu ț Pistol

2
UNIVERSITATEA “ALEXANDRU IOAN CUZA” DIN IA ȘI
FACULTATEA DE INFORMATICĂ

XMLStats: aplicație web pentru
analiza documentelor XML

Cosmin -Alexandru Dochi ței

Sesiunea : Iulie, 2020

Coordonator științific
Lect. Dr. Ionu ț Pistol

3

Cuprins

Introducere ………………………….. ………………………….. ………………………….. ………………………….. ………………. 5
Contribuții ………………………….. ………………………….. ………………………….. ………………………….. ………………… 6
1 Tehnologii utilizate ………………………….. ………………………….. ………………………….. ………………………….. 7
1.1 Java ………………………….. ………………………….. ………………………….. ………………………….. ……………. 7
1.2 TypeScript ………………………….. ………………………….. ………………………….. ………………………….. ….. 8
1.3 Apache Maven ………………………….. ………………………….. ………………………….. ………………………… 9
1.4 Apache Xerces ………………………….. ………………………….. ………………………….. …………………………. 9
1.5 Spring Framework / Spring Boot ………………………….. ………………………….. ………………………….. . 10
1.6 Angular ………………………….. ………………………….. ………………………….. ………………………….. …….. 12
1.7 Bootstrap ………………………….. ………………………….. ………………………….. ………………………….. …. 13
2 Proiectarea soluției ………………………….. ………………………….. ………………………….. ……………………….. 14
2.1 Arhitectura ………………………….. ………………………….. ………………………….. ………………………….. .. 14
2.2 Arhitectura aplicației client ………………………….. ………………………….. ………………………….. ……… 15
2.3 Arhitectura aplicației ser ver ………………………….. ………………………….. ………………………….. …….. 17
3 Implementarea soluției ………………………….. ………………………….. ………………………….. ………………….. 18
3.1 Implementarea aplicației server ………………………….. ………………………….. ………………………….. . 18
3.1.1 Structură ………………………….. ………………………….. ………………………….. ……………………….. 18
3.1.2 Controller de tip REST ………………………….. ………………………….. ………………………….. ……… 19
3.1.3 Încărcarea și validarea unui fișier XML ………………………….. ………………………….. …………… 20
3.1.4 Generarea de statistici pentru un fișier XML ………………………….. ………………………….. …… 23
3.1.5 Extragerea de date cu XPath ………………………….. ………………………….. …………………………. 26
3.1.6 Generarea de rapoarte cu statistici ………………………….. ………………………….. ……………….. 27
3.2 Implementarea aplicației client ………………………….. ………………………….. ………………………….. .. 29

4
3.2.1 Structură ………………………….. ………………………….. ………………………….. ……………………….. 29
3.2.2 Componenta upload -file ………………………….. ………………………….. ………………………….. ….. 30
3.2.3 Componenta statistics ………………………….. ………………………….. ………………………….. …….. 31
Concluzii ………………………….. ………………………….. ………………………….. ………………………….. …………………. 33
Funcționalități de editare a documentelor ………………………….. ………………………….. ……………………….. 33
Sistem de înregistrare, autentificare și gestiune a documentelor ………………………….. …………………….. 34
Bibliografie ………………………….. ………………………….. ………………………….. ………………………….. ……………… 35
Anexa 1 – Manual de utilizare ………………………….. ………………………….. ………………………….. ………………… 36
Pagina Home ………………………….. ………………………….. ………………………….. ………………………….. ……….. 36
Pagina Uploads ………………………….. ………………………….. ………………………….. ………………………….. …….. 36
Pagina Statistics ………………………….. ………………………….. ………………………….. ………………………….. …… 38

5
Introducere
Odată cu progresul tehnologic și, implicit , cu expansiunea continuă a spațiului World Wide
Web , numărul de utilizatori a crescut constant , volumul de date generat fiind, în consecință, din ce
în ce mai mare. Astfel, am putea spune că modurile de transferar e, prelucare și stocare a datelor ,
precum și menținerea unui nivel ridicat de securitate a informației , sunt cele mai importante
aspecte în dezvoltarea de aplicații web.
În prezent , din punct de vedere al datelor create pe internet , putem echivala o zi cu
următoarele valori : peste patru milioane de ore de conținut încărcate pe YouTube , 4.3 miliarde de
mesaje postate pe Facebook , 293 de miliarde de email -uri trimise.1
Necesitatea utilizării unui mod standard izat de transferare și stocare a datelor în mediul
virtual a dus la crearea mai multor meta -limbaje de marcare , cel mai popular și utilizat în această
privință fiind XML (Extensible Markup Language) . Ulterior, studiul resurselor XML din punct de
vedere al structurii și al conținutului a devenit un aspect tot mai important , în prezent existând
numeroase aplicații și framework -uri cu rol în validarea, parsarea, editarea structurilor și
extragerea conținutului . Câteva exemple sunt editoarele precum oXygen și XMLSpy , ce permit ,
printre altele , modificarea documentelor XML , validarea sintactică și conversia în alte formate și
extensiile pentru browsere ce oferă funcții de interogare ș i extragere a datelor , precum XPath
Helper pentru Google Chrome.
Proiectul realizat oferă o îmbinare a mai multor funcționalități prezente în aplicațiile
similare menționate mai sus , accentul fiind pe extragerea de date statistice privind structura
documentelor . Aceste funcționalități sunt implementate sub forma unei aplicații web cu o interfață
intuitivă.
Această lucrare conține trei capitole : Tehnologii utilizate , Proiectarea soluției și
Implementarea soluției , ce oferă o descriere a tehnologiilor selectate, a arhitecturii și a detaliilor
de implementare a aplicației . De asemenea , o anexă cu instrucțiuni de utilizare a aplicației este
atașată l a finalul lucrării.

1 https://blog.microfocus.com/how -much -data -is-created -on-the-internet -each -day/

6
Contribuții
O primă contribuție în realizarea acestei lucrări o reprezintă etapa de cercetare , ce a constat
în studiul tehnologiilor curente de reprezentare și transfer al datelor în spațiul web , analiza
funcționalităților oferite de aplicațiile de pe piață dedicate modelării și extragerii de date din
documente de tip XML , precum și studiul unor articole ce au ca temă de cercetare analiza modului
de structurare al diverselor documente de acest tip de pe internet și extragerea de date statistice .
Alte contribuții sunt reprezentat e de etapele de proiectare și implementare a soluției . Etapa
de proiectare a presupus studierea unor tehnologii care să vină în ajutor la implementarea
funcționalităților de analiză a documentelo r, precum și aprofundarea principiilor de creare de
aplicații cât mai modulare , soluția fiind astfel compusă din două aplicații independente : o aplicație
pe partea de client , ce se ocupă strict cu afișarea datelor preluate de la aplicați a server , comunicarea
realizându -se prin intermediul cereri lor HTTP.
Avantaj ele acestui stil de proiectare sunt: funcționalitățile noi pot fi adăugate independent ,
atât pe partea de client cât și pe cea de server și, totodată, serviciile aplicației server pot fi utilizate
de mai multe aplicații client.
În ceea ce privește etapa de implementare , modul de proiectare gândit a fost pus în aplicare ,
iar principiile de design software , precum SOLID2, ce au rolul de a face codul scris mai flexibil și
mai ușor de modificat , au fost respectate cât mai cu putință.
Astfel, putem spune că lucrarea curentă oferă o rezolvare la problema existenței unei
aplicații web moderne care să conțină o îmbinare de funcționalități pentru analiza documentelor
XML, extragerea datelor și generarea de rapoarte.

2 https://stackify.com /solid -design -principles/

7
1 Tehnologii utilizate
1.1 Java
Limbajul de programare Java este un limbaj orientat -obiect, dezvoltat de compania Sun
Microsystems în 1995, afl ându-se și în prezent în topul celor mai populare și utilizate limbaje din
industrie.
Din multitudinea de caracteristici ce au condus la popularitatea limbajului de programare
Java, printre cele mai relevante sunt (Frăsinaru, 2005) :
• Portabilitatea : în urma compil ării codului surs ă scris în Java, se genereaz ă așa
numitul bytecode, cod independent de ma șină, ce poate fi interpretat ulterior pe
orice platform ă cu ajutorul JVM (Java Virtual Machine), aceast ă caracteristic ă dând
naștere conceptului WORA (Write Once, Run Everywhere) ;
• Robustețea: caracteristic ă atins ă prin eliminarea pointerilor pentru evitarea
problemelor de corupere a datelor, nepermiterea mo ștenirii multiple și
managementul automat al memoriei (dealocarea memoriei fară referin țe fiind
îndeplinit ă de un proces ce ruleaz ă în fundal, numit garbage collector) ;
• Neutralitatea arhitectural ă: nu exist ă elemente de implementare dependente de o
anumit ă arhitectur ă, de exemplu, dimensiunea tipurilor primitive (int, byte, short)
este fix ă atât pentru arhitecturile pe 32 bi ți, cât și pe cele pe 64 bi ți;
• Complet orientat obiect : cu excep ția tipurilor primitive, totul este implementat
sub form ă de clase ce mo ștenesc direct sau indirect clasa Object, renun țându-se
astfel la stilul de programare procedural .
Exemplu de cod scris în Java:
StringBuilder builder = new StringBuilder();
builder.append( "Content type is not one of: " );
for (String fileType : fileManagementService .getFileTypes()) {
builder.append( fileType );
builder.append( " ");
}
throw new FileLogicException( builder.toString());

8
1.2 TypeScript
TypeScript este un limbaj de programare open source dezvoltat si men ținut de Microsoft.
Este un superset sintactic al limbajului JavaScript și asigur ă un sistem de tipuri opțional.3
Caracteristicile principale ale acestui limbaj sunt:
• Permite tastare static ă, ajut ând de exemplu la reducerea bug -urilor cauzate de
ipoteze gre șite ale unor tipuri de variabile ;
• Afișează erorile la compilare, spre deosebire de JavaScript care le afi șează la
execu ția programului ;
• Ruleaz ă pe orice browser JavaScript, orice cod scris in TypeScript fiind complet
valid și în JavaScript ;
• Pentru descrierea datelor pot fi utilizate tipuri, interfețe, aceste concepte fiind
inexistente în JavaScript .

Exemplu de cod scris în TypeScript:4
interface OS {
name: string;
language : string;
}
const desert = (type: OS): void => {
console.log('Android ' + type.name + ' has ' + type.language + '
language' );
};

const nougat = {
name: 'N',
language : 'Java'
}

desert(nougat);

3 https://en.wikipedia.org/wiki/TypeScript
4 https://appdivide nd.com/2019/01/15/typescript -tutorial -example -beginners -guide -to-typescript/

9
1.3 Apache Maven
Maven este un instrument de gestiune a proiectelor software (utilizat în principal pentru
proiectele scrise în Java, însă poate fi folosit și pentru proiecte scrise în alte limbaje de
programare), ce ofer ă o serie de func ționalit ăți, printre cele mai relev ante fiind gestiunea automat ă
a build -ului (validarea, compilarea, execu ția testelor , instalarea etc.), gestiunea dependen țelor
necesare proiectului, a versiunilor, precum și crearea de documenta ție.
Toate aceste func ționalit ăți, unele dintre ele op țional e, sunt descrise de dezvoltator într-un
fișier de configurare în format xml cu denumirea standard de pom.xml. Acesta reprezint ă nucleul
instrumentului Maven, av ând o structur ă generic ă pentru orice proiect, însă pot fi ad ăugate și alte
funcționalit ăți mai complexe .
Gestiunea dependen țelor este realizat ă de asemenea la procesul de build, ini țial fiind
descărcate dintr -un repository central și stocate într-un repository local, cel din urm ă având ulterior
rol de cache pentru preluarea mai rapid ă a acestor a. Orice dependen ță necesar ă trebuie ad ăugată
în pom.xml respect ând o structur ă standard format ă din trei tag -uri (groupId, artifactId, version).

1.4 Apache Xerces
Apache Xerces este o bibliotec ă ce ofer ă implement ări pentru standardele de procesare a
documentelor XML :
• DOM (Document Object Model): procesare ce implic ă încărcarea complet ă a
documentului în memorie și crearea unei structuri arborescente, elementele
putând fi parcurse în sens bidirec țional ;
• SAX (Simple API for XML): procesare bazat ă pe eve nimente, cu încărcarea
parțială a documentului pe masur ă ce este procesat ;
• StAX (Streaming API for XML): procesare similar ă cu SAX , cu c âteva
funcționalit ăți în plus specifice DOM, de exemplu posibilitatea de a modifica
fișiere XML .
Xerces ofer ă funcționalit ăți de parsare, validare și manipulare a datelor din documente
XML, fiind util în sarcinile de analiz ă și prelucrare ale acestora.

10
Câteva dintre interfe țele oferite pentru procesare a DOM sunt Node , Element , Attribute ,
reprezent ând elementele, respectiv atributele lor dintr -un document XML, iar c âteva metode
standard sunt Document.getDocumentElement(), Node.getFirstChild(), Node.getLastChild() .
Încărcarea unui document XML se face prin:
DocumentBuilder builder =
DocumentBuilderFactory .newInstance ().newDocumentBuilder();

Document document = builder.parse(new File(“exemplu.xml”));

Preluarea primului element dintr -o mul țime de elemente cu acela și nume:
NodeList nodeList = document .getElementsByTagName(“pret”);

Node firstNode = nodeList .item(0);

Traversarea nodurilor copil ale primului element cu nume “pre ț” și afișarea con ținutului
lor:
NodeList childList = firstNode.getChildNodes();
Node currentNode ;
for(int i = 0; i < childList .getLength(); i++) {
currentNode = childList .item(i);

if(currentNode .getNodeType == Node.ELEMENT_NODE) {
System.out.println( currentNode .getNodeName() + “: “ +
currentNode .getTextContent());
}
}

1.5 Spring Framework / Spring Boot
Spring este o bibliotec ă popular ă, utilizat ă pentru dezvoltarea de aplica ții în Java. Ini țial o
alternativ ă mai u șoară față de Java E nterprise Edition în dezvoltarea de aplica ții complexe , Spring
cuprinde în prezent un ecosistem complet, oferind solu ții și proiecte în aproape toate ariile de
dezvoltare web.

11
Func ționalit ățile ce au stat la baza dezvoltării Spring sunt inversiunea controlului și
injectarea de dependen țe. Inversiunea controlului este un principiu din ingineria software ce
implic ă transferarea controlului obiectelor sau a anumitor por țiuni de program c ătre un container
sau o bibliotec ă, fiind folosit cel mai des în programarea orientat ă-obiect .5
Injectarea de dependen țe reprezint ă externalizarea func ționalit ăților unor obiect e prin
adăugarea acestora ca dependen țe ale u nor obiecte de tip “factory” , cre ând astfel leg ături și
menținând un cuplaj redus.
@RestController
public class UserController {

private final UserRepository userRepository ;

public UserController (UserRepository userRepository) {
this.userRepository = userRepository;
}

@GetMapping( "/users" )
public List<User> getUsers () {
return (List<User>) userRepository .findAll();
}

@PostMapping( "/users" )
void addUser(@RequestBody User user) {
userRepository .save(user);
}
}

În exemplul de mai sus, c lasa adnotat ă cu @RestController reprezint ă o interf ață de tip
REST.6 De asemenea, adnot ările de tipul @GetMapping , @PostMapping leagă cererile de tip
GET, POST la metode specifice din clasa de tip controller. Clasa de tip @Repository
(UserRepository în exemplu) ofer ă imple mentări standard pentru opera țiile CRUD (Create, Read,
Update, Delete, opera țiile standard asupra unei baze de date rela ționale) și creeaz ă o leg ătură între
partea de logic ă Java și entitatea User din baza de date.

5 https://www.baeldung.com/inversion -control -and-dependency -injection -in-spring
6 https://restfulapi.net/

12
Spring Framework este compus din mai multe module, c âteva dintre ele fiind:
• Core : ofer ă funcționalit ăți de baz ă, precum injectarea de dependen țe, validare,
interna ționalizare ;
• Data Access : oferă funcționalit ăți de acces și manipulare a datelor stocate utiliz ând
JTA (Java Transaction A PI), JPA (Java Persistence A PI) și JDBC (Java Database
Connectivity) ;
• Web : ofer ă suport pentru Servlet A PI prin Spring MVC (Model View Controller),
WebSockets, WebClient etc.
În prezent exist ă mai multe proiecte dezvoltate peste biblioteca original ă Spring, oferind
soluții pentru toate nevoile curente în dezvoltarea de aplica ții enterprise:
• Spring Boot : necesit ă și mai pu ține configur ări ini țiale din partea dezvoltatorului,
oferind posibilitate a de a începe rapid implementarea unui proiect enterprise de sine
stătător
• Spring Cloud
• Spring Security

Spring Boot este un proiect din ecosistemul Spring al c ărui principal scop este minimizarea
configur ărilor manuale, necesare pentru începerea dezvolt ării unui proiect. Prin urmare, Spring
Boot execut ă configur ări automate pe baza unor fi șiere de propriet ăți, rezolv ă dependen țele și ofer ă
un server HTTP deja configurat. Crearea unui proiect cu Spring Boot se face utiliz ând un
configurator online numit Spring Initializr.

1.6 Angular
Angular , numit și Angular 2, este un framework utilizat pentru construirea de aplica ții web
pe o singur ă pagin ă pe partea de client . Acesta aduce o serie de noi funcționalități și optimizări
față de predecesorul său AngularJS . O primă diferență între cele două este înlocuirea limbajului
JavaScript cu supersetul său TypeScript .

13
De asemenea, arhitectura clasică MVC (Model -View -Controller) din AngularJS este
schimbată cu o arhitectură orientată pe componente , introducându -se de asemenea concepte
precum module, servicii si directive.
Fiind un produs Google, acest framework poate fi considerat o alegere sigură și de
încredere pentru dezvoltarea de aplicații pe p artea de client, dispunând de asemenea de o
comunitate foarte largă de dezvoltatori, documentații complexe și actualizări frecvente.

1.7 Bootstrap
Bootstrap este un framework CSS open -source folosit pentru design -ul paginilor web,
dezvoltat inițial la Twitter . Acesta oferă componente responsive ce pot fi utilizate în paginile
HTML , suport pentru diverse plugin -uri JavaScript, precum și o multitudine de stilizări pentru
elementele HTML . O altă funcționalitate importantă este sistemul de împărțire a pagin ii în 12
coloane, numit Grid System, utilizat în crearea șabloanelor și așezarea uniformă a elementelor în
pagină.
Exemplul de mai jos creează trei coloane egale, folosind clasele predefinite ale sistemului
de împărțire, container , row, col.7
div class="container" >
<div class="row">
<div class="col-sm">
One of three columns
</div>
<div class="col-sm">
One of three columns
</div>
<div class="col-sm">
One of three columns
</div>
</div>
</div>

7 https://getbootstrap.com/docs/4.0/layout/grid/

14
2 Proiectarea soluției
2.1 Arhitectura
Soluția este compusă dintr -o aplicație pe partea de client, dezvoltată în Angular și o
aplicație pe partea de server, dezvoltată în stil REST utilizând Spring Boot , comunicarea între
client și server realizându -se prin int ermediul cererilor HTTP inițiate de client și a răspunsurilor
returnate de server . Un beneficiu principal al acestui mod de proiectare este independența interfeței
față de logica părții de back -end.

Figura 1 – Arhitectura aplicației 8

8 https://blog.angular -university.io/developing -a-modern -java-8-web -app-with -spring -mvc-and-angularjs/

15
2.2 Arhitectura aplicației client
Arhitectura unei aplicații Angular se bazează pe câteva elemente fundamentale: module,
componente și servicii.
• Modulele reprezintă echivalentul pachetelor din alte limbaje de programare, ce
încapsulează anumite funcționalități. Fiecare aplicație Angular are un modul
principal ce poate importa la rândul său alte module. Un modul poate conține
componente, furnizori de servicii etc.
@NgModule ({
declarations : [
AppCompone nt,
GetWordsComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
BrowserAnimationsModule
],
providers : [],
bootstrap : [AppComponent]
})
export class AppModule { }

Exemplu de decla rare a unui modul, acesta fiind o clasă adnotată cu @NgModule ,
decorator cu anumite proprietăți ce descriu modulul, cum ar fi componentele și serviciile
utilizate sau alte module importate.
• Componentele , la fel ca și modulele, sunt clase adnotate cu un decorator specific,
ce au rolul de a defini un view. Deoarece Angular oferă funcționalități pentru
construirea de aplicații bazate pe o singură pagină, experiența utilizatorului și iluzia
navigării pe mai multe pagini este obținută folosind mai multe view -uri, ce sunt
afișate sau ascunse în funcție de anumite logici, obținându -se o structură ierarhică
cu leg ătura de bază la singura pagin ă HTML a aplicației. Componenta principal ă a
unei aplicații Angular est e AppComponent. Decoratorul @Component definește un
selector (modul de inserare a componentei în interfață), leg ătura către șablonul
HTML , precum și cea către fișierul de stilizare. Prin urmare, o clasă decorată cu

16
@Component , împreună cu șablonul HTML respectiv, formează un view pentru
pagina principală a aplicației.
• Serviciile sunt clase care au rolul de a îndeplini o singură sarcină, conform primului
principiu SOLID . Spre deosebire de componente, al cărui principal rol este
preluarea și prezentarea datelor în view -ul asignat, serviciile sunt folosite cel mai
des în sarcinile de preluare a datelor de la aplicații server. După declarare, un
serviciu poate fi injectat în orice componentă ca dependență și poate folosi la rândul
său alte servicii.
În implementarea aplicației client, arhitectura Angular a fost urmată în detaliu, singura
diferență fiind utilizarea unor clase cu rolul de model ce preiau datele de la servicii și le
transferă la componente, acest lucru oferind un aspec t MVC arhitecturii.

Figura 2 – Arhitectura unei aplicații Angular9

9 https://angular.io/guide/architecture

17
2.3 Arhitectura aplicației server
Aplicația de la nivelul server, implementată folosind Spring Boot , are o arhitectură
stratificată, fiecare strat fiind capabil de a comunica cu predecesorul și succesorul său. La primul
nivel se află Controller -ul, cu rol în preluarea cererilor HTTP venite de la client . Fiecare cerere
este asignată unei metode specifice , care apelează la rândul ei metode din stratul servic iilor, acestea
din urmă comunicând cu clasele ce realizează logica de business sau de persistență a datelor.

Figura 3 – Arhitectura unei aplicații Spring Boot 10

Pentru implementarea aplicației server, această arhitectură a fost urmată , cu câteva
diferențe:
• Logica de business nu e realizată în totalitate în stratul serviciilor, clasele respective
utilizând la rândul lor metode din alte clase utilitare, acest aspect având rolul de a
extinde modularitatea;
• Luând î n considerare inexistența unei baze de date pentru această aplicație, stratul
cu rol în persistența datelor a fost omis.

10 https://www.javatpoint.com/spring -boot -architecture

18
3 Implementarea soluției
3.1 Implementarea aplicației server
3.1.1 Structură
Aplicația server este scrisă în Java , care utilizează Spring Boot ca framework ajutător ,
acesta creând automat configurări necesare execuției unei aplicații web și eliminând , astfel , o mare
parte din fișierele de configurări repetitive în aplicațiile web scrise în Java . De asemenea,
framework -ul are integrat Apache Tomcat ca server de aplicații .
Fișierul de configurare Maven, pom.xml , conține informații necesare pentru construirea
proiectului, printre care numele proiectului, dependențele acestuia, versiunile etc.
<?xml version ="1.0" encoding ="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema -instance"
xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven -4.0.0.xsd" >
<modelVersion >4.0.0</modelVersion >
<parent>
<groupId>org.springframework.boot </groupId>
<artifactId >spring-boot-starter-parent</artifactId >
<version>2.2.6.RELEASE </version>
<relativePath /> <!– lookup parent from repository –>
</parent>
<groupId>com.project </groupId>
<artifactId >analyzer </artifactId >
<version>0.0.1-SNAPSHOT </version>
<name>analyzer </name>
<description >Xml Analyzer Project </description >

<properties >
<java.version >1.8</java.version >
</properties >

<dependencies >
<dependency >
<groupId>org.springframework.boot </groupId>
<artifactId >spring-boot-starter-web</artifactId >
</dependency >
</dependencies >

Totodată, proiectul este împărțit în mai multe pachete compuse din clase cu roluri similare,
cum ar fi controllers , ce conține clase de tip controller , services și models pentru clase servicii,
respectiv modele.

19
3.1.2 Controller de tip REST
Adnotarea @RestController marchează clasa XmlAnalyzerController ca fiind punctul
principal de acces al aplicației, dezvoltată în manieră Restful . Aceasta preia cererile HTTP,
direcționându -le către metode adnotate la rândul lor cu tipul cererii și endpoint -ul respectiv .
Răspunsurile metodelor sunt serializate în format JSON și returnate ca răspunsuri HTTP .
@RestController
@CrossOrigin ("http://localhost:4200" )
@RequestMapping ("/api")
public class XmlAnalyzerController

@CrossOrigin activează funcția de partajare a resurselor încrucișate (Cross -origin resource
sharing 11), permițând în acest exemplu accesul la resurse pentru cererile venite de la originea
localhost:4200 (adresa locală pentru aplicația client). @RequestMapping adaugă calea / api în fața
tuturor căilor de acces către resursele definite.
@GetMapping ("/statistics/pdf" )
public ResponseEntity <byte[]> retrievePdfFile (@RequestParam ("fileName" )
String fileName) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders .setContentType( MediaType .APPLICATION_PDF );
return new
ResponseEntity<>( pdfGenerationService .createPdfDocument(fileName,
xmlAnalyzerService ), httpHeaders , HttpStatus .OK);
}

Adnotarea @GetMapping(“/statistics/pdf”) mapează cererile HTTP de tip GET către
resursa /statistics/pdf la metoda retrievePdfFile (). În cadrul acesteia este apelat serviciul
responsabil cu generarea unui raport pdf cu statistici pentru fișierul setat ca parametru al cererii.
Ca tip de răspuns este folosit ResponseEntity , acesta având formatul unui răspuns HTTP și
permițând includerea de elemente specifice precum antet, corp, status . În exemplul ilustrat, clasa
HttpHeade rs este utilizată pentru a seta tipul de conținut returnat.

11 https:/ /developer.mozilla.org/en -US/docs/Web/HTTP/CORS

20
3.1.3 Încărcarea și validarea unui fișier XML
Încărcarea fișierelor în aplicație se poate realiza în două moduri: încărcarea din spațiul de
stocare local sau încărcarea de la un URL specificat. La momentul încărcării este inițializată logica
de validare, ce implică verificarea tipului de fișier, corectitudinea URL -ului, verificarea sintaxei și
validarea cu un fișier precum XSD sau DTD.
XSD (Xml Schema Definition) și DTD ( Document Type Definition) sunt fișiere de
validare ce definesc reguli privind modul de structurare al fișierelor XML, câteva exemple fiind:
elemen tele/atributele care pot apărea, tipul acestora, precum și elementele care au copii, numărul
și tipul acestora etc.

Figura 4 – Exemplu de fișier XML cu DTD 12
Exemplul de mai sus ilustrează un fișier XML cu un DTD intern , ce definește structura
acestuia.
public boolean checkUrl (String url) {
try {
URL urlFile = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
throw new BadUrlException(e.getMessage());
}
return url.endsWith( ".xml") || url.endsWith( ".xsd") ||
url.endsWith( ".dtd");
}

12 http://inf.ucv.ro/~mihaiug/courses/xml/ValidareaDocumentelorXML.html#d0e50

21
Metoda checkUrl(String url) verifică corectitudinea unui URL și faptul că acesta referă un
fișier XML ori XSD/DTD, în cazul validării fișierului contra unui set de reguli aflat într -un fișier
de validare extern ce trebuie de asemenea încărcat.
public void saveFileFromUrl (String url) throws IOException {
URL fileUrl = new URL(url);
String[] fileNamePath = fileUrl.getFile().split( "/");
Files.copy(fileUrl.openStream(),
rootDirectory .resolve( fileNamePath [fileNamePath .length – 1]),
StandardCopyOption .REPLACE_EXISTING );
}

Metoda saveFileFromUrl(String url) salvează conținutul fișierului de la URL -ul specificat ,
numele acestuia fiind extras din link. Opțiunea StandardCopyOption.REPLACE_EXISTING
rezolvă conflictul fișierelor cu același nume prin înlocuire.
După încărcarea cu succes a fișierului XML , urmează procesul de verificare a sintaxei , ce
constă în aplicarea unor reguli standard precum prezența tag-urilor de închidere pentru fiecare
element , prezența unui element rădăcină etc. Această sarcină este realizat ă în cadrul aplicației cu
ajutorul librăriei Apache Xerces , folosind modul de procesare DOM, descris în capitolul de
tehnologii utilizate.
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory .newInstance ();
documentBuilderFactory .setNamespaceAware( true);
documentBuilderFactory .setValidating( false);

Pentru parsarea unui fișier XML în stil DOM și verificarea corectitudinii s intaxei este
creată o instanță a obiectului DocumentBuilderFactory , setarea atributului de validare cu valoarea
fals indicând că nici o altă validare cu fișier extern nu trebuie efectuată.
private static final String EXTERNAL_ENTITY =
"http://xml.org/sax/features/external -general-entities" ;
private static final String EXTERNAL_ENTITY_PARAMETER =
"http://xml.org/sax/features/external -parameter -entities" ;

private static void disableExternalEntities (DocumentBuilderFactory
documentBuilderF actory) throws ParserConfigurationException {
documentBuilderFactory.setFeature( EXTERNAL_ENTITY , false);
documentBuilderFactory.setFeature( EXTERNAL_ENTITY_PARAMETER , false);
}

22
De asemenea , ca o măsură în plus de securitate , parsarea entităților externe este dezactivată ,
pentru a preveni atacuri de tipul XXE (XML eXternal Entity injection ), acest lucru fiind în
conformitate cu recomandările de securitate ale OWASP13 (Open Web Application Security
Project ).
Document document ;
DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
if (xmlFile != null) {
documentBuilder .setErrorHandler( new ValidationErrorHandler(xmlFile));
document = documentBuilder .parse(xmlFile.getInputStream());
document.getDocumentElement().normalize();
}

Din DocumentBuilderFactory este instanțiat un DocumentBuilder , cu rolul de a parsa
conținutul fișierului XML, obținându -se în final un Document ce poate fi parcurs și analizat în
mod arborescent. Un handler specific pentru erori este setat pentru prinderea excepțiilor aruncate
în cazul erorilor de sintaxă semnalate. Acestea sunt prinse în trei categorii diferite : warning, error
și fatal error , pentru ultimele două fiind apelată și funcția de ștergere a fișierului încărcat. Erorile
specifice aruncate trec printr -o clasă adnotată cu @ControllerAdvice , în care acestea s unt
împachetate în răspunsuri HTTP și trimise către aplicația client.
@ControllerAdvice
public class ExceptionManager {
@ExceptionHandler
public ResponseEntity <ExceptionResponse >
handleFileUploadException (FileLogicException exception) {
ExceptionResponse response = new
ExceptionResponse(exception.getMessage(),
HttpStatus .INTERNAL_SERVER_ERROR .value());
return new ResponseEntity<>( response ,
HttpStatus .INTERNAL_SERVER_ERROR );
}

În exemplul de mai sus, FileLogicException este împachetat în răspuns HTTP cu statusul
INTERNAL_SERVER_ERROR.

13 https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html

23
Pentru validarea unui fișier XML contra unui set de reguli specificat într -un fișier extern
de tip XSD sau DTD , este necesară încărcarea în prealabil a acestor fișiere și referirea lor în fișierul
XML . Erorile de sintaxă dintr -un fișier XSD sunt detectate la momentul parsării ce se realizează
identic ca la fișierele XML. Pentru fișier DTD, erorile acest uia sunt semnalate la momen tul
validării fișier ului XML contra regulilor definite.
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory .newInstance ();
documentBuilderFactory .setNamespaceAware( true);
documentBuilderFactory .setValidating( true);

Validarea contra unui fișier DTD extern referit în cadrul XML -ului este realizată prin
setarea atributului de validare din DocumentBuilderFactory pe true.
private static final String XSD_ATTRIBUTE_NAME =
"http://java.sun.com/xml/jaxp/properties/schemaLanguage" ;
private static final String XSD_ATTRIBUTE_VALUE =
"http://www.w3.org/2001/XMLSchema" ;
documentBuilderFactory .setNamespaceAware( true);
documentBuilderFactory .setValidating( true);
documentBuilderFactory .setAttribute( XSD_ATTRIBUTE_NAME , XSD_ATTRIBUTE_VALUE );

La validarea contra unei scheme de tip XSD , pe lângă setarea atributului de validare cu
valoarea true, este setat și un atribut cu o valoare standard ce semnalează parser -ului prezența unei
referințe către un XSD în fișierul XML respectiv.

3.1.4 Generarea de statistici pentru un fișier XML
Statisticile oferite de aplicație sunt realizate prin parcurgerea și analiza arborelui de noduri
creat prin parsarea fișierului cu DOM. Pentru a cuprinde toate elementele specifice unui XML,
sunt definite mai multe tipuri de noduri în cadrul DOM API , cele mai utilizate fiind Element,
Attribute, Text.
Câteva exemple de statistici generate sunt : num ărul total de elemente, atribute, elemente
copil și elemente identice consecutive , numărul de apariții ale unui anumit element sau atribut ,
calcularea de valori precum sumă, medie , deviație standard pentru elemente sau atribute cu valori
numerice etc.

24
private static final String FLOATING_POINT_NUMBER_PATTERN ="[+-]?([0-
9]*[.])?[0 -9]+";
public static Map<String, Float> getStatisticsForElementNumericValues (String
fileName, String elementTagName) {
xmlDocument = XmlFileValidator .getValidatedDocument (fileName);
NodeList nodeList = xmlDocument .getElementsByTagName(elementTagName);
if (nodeList != null) {
List<String> numericValues = new ArrayList<>();
String elementValue = "";
for (int i = 0; i < nodeList .getLength(); i++) {
elementValue = nodeList .item(i).getFirstChild().getNodeValue();
if (elementValue.matches( FLOATING_POINT_NUMBER_PATTERN )) {
numericValues .add(elementValue);
}
}
if (!numericValues .isEmpty()) {
return calculateStatisticsForNumericValues (numericValues );
}
}
return new HashMap<>();
}

Metoda getStatisticsForElementNumericValues ilustrată mai sus realizează calcule pentru
valorile numerice ale unui anumit element dintr -un fișier. Lista tuturor aparițiilor elementului este
creată apelând getElementsByTagName(elementTagName) , ce returnează o interfață de tip
NodeList. În continuare, pentru fiecare el ement din listă, se compară valoarea acestuia contra unei
expresii regulate, cu scopul de a crea o listă cu valorile de tip numeric. Pentru această listă sunt
calculate ulterior valoarea minimă, maximă, suma, media, suma pătratelor și deviația standard.
O altă metodă interesantă constă în parcurgerea tuturor nodurilor din arborele generat
pentru a extrage conținutul text. Pentru această sarcină, trebuie selectate nodurile frunză de tip
Element . De asemenea, textul extras trebuie „curățat ” de caractere speciale (new line, new tab,
return) și de spații multiple.
List<String> textDataList = new ArrayList<>();
Element rootElement = xmlDocument .getDocumentElement();
NodeList nodeList = rootElement .getElementsByTagName( "*");
for (int i = 0; i < nodeList .getLength(); i++) {
if (nodeList .item(i).getNodeType() == Node.ELEMENT_NODE &&
!hasElementChild (nodeList .item(i))) {
String content =
nodeList .item(i).getTextContent().trim().replaceAll( MULTIPLE_SPACES_PATTERN ,
" ")
.replaceAll( "\n", "").replaceAll( "\t", "");
textDataList .add(content);
}
}

25
Fragmentul de cod de mai sus realizează sarcina de extragere a conținutului te xt. Elementul
rădăcină al fișierului este extras cu metoda getDocumentElement() , iar apelul
getElementsByTagName("*") returnează o listă cu toate nodurile de tip Element din document.
Pentru calcularea adâncimii maxime a arborelui, respectiv a numărului de elemente și
atribute aflate la fiecare nivel de adâncime , este apelată o funcție ce parcurge arborele în mod
recursiv și populează două structuri de tip Map , elementsDepth respectiv attributesDep th, ce
conțin perechi de tip cheie -valoare.
private static void traverseNodeList (int depth, NodeList nodeList) {
if (nodeList != null) {
depth = depth + 1;
maxDepth = depth;
for (int i = 0; i < nodeList.getLength(); i++) {
Node currentNode = nodeList.item(i);
if (currentNode .getNodeType() == Node.ELEMENT_NODE ) {
if (elementsDepth .get(depth) == null) {
elementsDepth .put(depth, 1);
} else {
elementsDepth .put(depth, elementsDepth .get(depth) + 1);
}
if (currentNode .getAttributes() != null) {
if (attributesDepth .get(depth) == null) {
attributesDepth .put(depth,
currentNode .getAttributes().getLength());
} else {
attributesDepth .put(depth, attributesDepth .get(depth) +
currentNode .getAttributes().getLength());
}
}
}
if (hasElementChild (currentNode )) {
traverseNodeList (depth, currentNode .getChildNodes());
}
}
}
}

Metoda traverseNodeList() parcurge lista de noduri asociate arborelui și populează cele
două mape în felul următor : pentru fiecare nod de tip element găsit la o anumită adâncime , se
verifică existența unei valori în elementsDepth . Dacă elementul găsit la acea adâncime este primul ,
se creează o nouă pereche cheie -valoare , altfel se incrementează valoarea pentru adâncimea
respectivă. Tot pentru nodul curent de tip element , se verifică existența unei mulțimi de noduri
atribut asociate acestuia și se repetă aceeași logică pentru popularea mapei attributesDepth . Într-
un final , în cazul existenței unei mulțimi de noduri copil , metoda intră în recursie.

26
Toate informațiile oferite sunt generate în mod similar, prin parcurgerea anumitor mulțimi
de noduri din arborele creat de parser -ul DOM . Metodele, create într -o clasă utilitară cu numele
XmlFileAnalyzer , sunt apelate de RestController prin intermediul unei alte clase de tip @Service.

3.1.5 Extragerea de date cu XPath
O altă modalitate de a extrage informații din fișiere XML încărcate în cadrul aplicației este
prin utilizarea XPath , un limbaj de interogare folosit pentru selectarea nodurilor din aceste fișiere
după diverse criterii. Totodată, acest limbaj oferă și funcții integrate pentru efectuarea de operații
numerice sau logice asupra m ulțimilor de noduri preluate.
Câteva exemple de expresii XPath utilizate sunt :
• /employees/employee – selectarea tuturor elementelor de tip employee ce sunt
descendenți direcți pentru elemente de tip employees;
• /employee/@name – selectarea tuturor atributelor de tip name ale elementelor de
tip employee;
• count(/employee) – selectarea numărului de elemente de tip employee .
Compilarea și evaluarea expresiilor se realizează cu ajutorul claselor XPath , XPathFactory
din cadrul pachetului javax.xml . Fragmentul de cod de mai jos , asemănător procesului de parsare
al fișierelor cu DOM , creează o instanță de tip factory , iar cu ajutorul acesteia , o instanță folosită
la compilarea propriu -zisă a expresiei primite ca argument. De asemenea , valorile din
XPathConstants sunt utilizate pentru setarea tipului de date returnat în urma evaluării cu succes a
expresiei.
XPathFactory xPathFactory = XPathFactory .newInstance ();
XPath xPathExpression = xPathFactory .newXPath();
try {
NodeList resultList = (NodeList )
xPathExpression .compile(expression).evaluate( xmlDocument ,
XPathConstants .NODESET);
} catch (XPathExpressionException e) {
e.printStackTrace();
throw new XPathSyntaxException(e.getLocalizedMessage());
}

27
3.1.6 Generarea de rapoarte cu statistici
Aplicația oferă suport pentru generarea a trei tipuri de rapoarte : pdf cu statistici generate
pentru un fișier XML , pdf cu conținutul text extras dintr -un singur fișier și excel cu statistici
generate pentru toate fișierele XML încărcate la un moment dat. În vederea generării acestor tipuri
de fișiere, au fost adăugate în pom.xml dependențe pentru API -urile de la itext pdf și Apache POI.
Procesul de creare a unui fișier pdf implică un flow asemănător celorlalte funcționalități
oferite de aplicație : preluarea unei cereri HTTP de tip GET către resursa /statistics/pdf și
inițializarea logicii de creare din clasa PdfGenerationService .
Pentru popularea și stilizarea documentului , sunt puse la dispoziție o multitudine de
interfețe precum Font , FontFactory pentru setarea de fonturi, Paragraph , Chunk , Element , Anchor
pentru organizarea și așezarea textului.
Font font = FontFactory .getFont(FontFactory .TIMES_ROMAN , 14,
BaseColor .BLACK);
Paragraph elementsParagraph = new Paragraph( "Elements number: " +
basicStatistics.get( "Elements" ).size(), font);
addSpaces( elementsParagraph , 1);

În fragmentul de cod de mai sus este creat un paragraf în care este setat un conținut cu
numărul de elemente ale fișierului XML selectat la acel moment , adăugându -se, de asemenea , un
font creat cu ajutorul clasei FontFactory .
Crearea de tabele în pdf este , totodată, realizată cu ajutorul claselor PdfPTable și PdfPCell ,
codul de mai jos generând un tabel cu șapte coloane pentru statisticile realizate asupra datelor de
tip numeric ale atributelor dintr -un XML.
PdfPTable attributesTable = new PdfPTable( 7);
attributesTable .addCell(createTableHeader( "Attribute" ));
attributesTable .addCell(createTableHeader( "Min"));

private PdfPCell createTableHeader (String name) {
PdfPCell pdfPCell = new PdfPCell( new Phrase(name));
pdfPCell .setHorizontalAlignment( Element.ALIGN_CENTER );
return pdfPCell ;
}

28
Pentru crearea unui pdf cu informațiile text extrase din XML , procesul este în mare parte
identic , acest document fiind chiar mai puțin complex din punct de vedere al paragrafelor și al
stilurilor adăugate.
La generarea raportului excel, sunt utilizate interfețele și clasele oferite de Apache POI ,
cum ar fi Workbook , Sheet , Row, Cell, Font , CellStyle . Pentru acest raport sunt d efinite patru foi
de lucru , ce conțin date pentru elemente, atribute, precum și pentru elementele și atributele
numerice extrase din toate fișierele XML încărcate.
Sheet elementsSheet = excelWorkbook .createSheet( "Elements" );
createTopCells( excelWorkbook , elementsSheet , elements );
Sheet attributesSheet = excelWorkbook .createSheet( "Attributes" );
createTopCells( excelWorkbook , attributesSheet , attributes );
Sheet numericElementsSheet = excelWorkbook .createSheet( "Numeric elements" );
createTopCells (excelWorkbook , numericElementsSheet , numericElements );
Sheet numericAttributesSheet = excelWorkbook .createSheet( "Numeric
attributes" );
createTopCells( excelWorkbook , numericAttributesSheet , numericAttributes );

Fragmentul de cod ilustrat se ocupă cu crearea foilor de lucru menționate și cu a celulelor
de tip header din fiecare foaie de lucru. Spre exemplu, foaia de lucru Elements conține trei coloane
cu headerele Elements, Occurrences și Is child.
Popularea cu date a foilor de lucru se face în felul următor : se parcurge lista documentelor
XML încărcate și, pentru fiecare document, se generează statistici pentru mulțimile de noduri de
tip element și atribut extrase.
for (String attribute : attributesSet ) {
Sheet attributesSheet = sheetList.ge t(1);
Row currentRow = attributesSheet .createRow(attributesRowIndex++);
Cell attributeCell = currentRow .createCell( 0);
attributeCell.setCellValue( attribute );
int attributeOccurrence =
xmlAnalyzerService.getAttributeOccurrences( currentDocument , attribute );
attributeCell = currentRow .createCell( 1);
attributeCell.setCellValue( attributeOccurrence );
}

Fragmentul de cod de mai sus populează foaia de lucru Attributes cu date privind numărul
de apariții al fiecărui atribut, proces repetat pentru toate documentele încărcate. Pentru fiecare
atribut, se creează un nou rând cu metoda createRow () și două celule cu metoda createCell ().

29
3.2 Implementarea aplicației client
3.2.1 Structură
Aplicația client este împărțită în trei pachete principale : components, models și services .
Fiecare componentă este formată dintr -o pagină html și o pagină css , formând un view ce poate fi
afișat pe pagina principală a aplicației, index.html . Pe lângă aces te pagini , orice componentă are și
o clasă typescript adnotată cu @Component în care este implement ată logica. Clasele din pachetul
services interacționează direct cu aplicația server, prin trimiterea de cereri HTTP, răspunsurile
primite fiind mapate în clasele de tip model , acestea din urmă fiind utilizate de componente pentru
afișarea datelor în interfață.

Figura 5 – Structura pachetelor aplicației client
Există de asemenea clase ce se ocupă cu logici de configurare, printre care app.module.ts ,
în care sunt importate toate componentele și modulele utilizate în aplicație , app-routing.module.ts
pentru configurarea căilor către componentele definite . În fișiere precum angular.json și
package.json sunt declarate dependențe și configurări pentru build -ul aplicației. Un alt fișier
utilizat este styles.css , pentru definirea globală a unor stilizări aplicabile diverselor elemente din
paginil e HTML.

30
3.2.2 Componenta upload -file
Această componentă implementează logica pentru importul de fișiere și trimiterea acestora
ca parametri în cereri HTTP la aplicația server . Partea de HTML ce corespunde componentei este
formată din elemente de tip button , dropdown, input file , utilizate pentru a crea o interfață cu toate
opțiunile de încărcare și validare oferite de aplicația server.
<div class="row" *ngIf="justSyntaxValidation ">
<div class="col text -center">
<select (change) ="changeDropdownOption ($event)" class="btn btn -light"
style="width: 17%">
<option value="local" >From local system </option>
<option value="url">From URL </option>
</select>
</div>

Fragmentul de mai sus, preluat din fișierul HTML, creează o listă derulantă (dropdown) cu
opțiunile From local system și From URL . Directivele specifice Angular , *ngIf și (change) ,
creează legătura între fișierul HTML și clasa TypeScript . Acestea utilizează variabile și metode
definite în clasă pentru crearea de condiții de afișar e, respectiv răspunsuri la event -uri de
schimbare , în interfață.
uploadXmlFile () {
this.fileUploadService .uploadXmlFile (this.selectedXmlFile ,
this.xmlFileUrl ).subscribe (data => {
this.message = data.message;
if (data.fileName ) {
sessionStorage .setItem(data.fileName , data.fileName );
}
}, error => {
this.errorMessage = error.error.message;
console.log(error);
});
}

Metoda uploadXmlFile() de mai sus apelează serviciul care comunică direct cu aplicația
server . Metodele implementate în clasele de tip serviciu returnează răspunsuri împachetate ca
Observable , ce implementează design pattern -ul Observer. Astfel, răspunsul poate fi returnat către
mai mulți observatori care au apelat în prealabil metoda subscribe , precum în exemplul ilustrat.

31
După importarea cu succes a fișie rului XML, numele acestuia este stocat pe sesiune cu
sessionStorage.setItem() , evitându -se astfel afișarea fișierelor importat e în multiple sesiuni ale
aplicației.

3.2.3 Componenta statistics
Această componentă are rolul de a afișa statisticile primite de la aplicația server pe baza
input -urilor preluate din interfață , în pagina HTML corespunzătoare componentei fiind afișat și un
tabel cu toate documentele XML încărcate . La selectarea unui document din tabel, sunt afișate
statisticile sale principale , elemente de interfață (input text, check box) pentru preluarea de
informații mai detaliate , grafice de tip plăcintă și opțiuni pentru generare de rapoarte.
<label for="attributesDepth" >Retrieve data with XPath expressions: </label>
<div class="flex pb -3">
<input autocomplete ="off" style="width: 40%" type="text"
(change) ="onChangeXPath ($event)" class="form-control" id="xPathData"
placeholder ="Enter expression" >
<button type="button" (click)="onClickXPath ()" class="btn btn -light mx –
5"><b>Get data </b></button>
</div>

Porțiunea de HTML de mai sus corespunde elementului de interfață de tip input text utilizat
pentru preluarea de expresii XPath ce interoghează arborele de noduri al documentului XML
curent . Directiva (click) asociază evenimentul de click al butonului definit cu execuția metodei
onClickXPath().
initializePieCharts () {
while (this.dataTagsChart .length > 0) {
this.dataTagsChart .pop();
}
this.dataTagsChart .push(this.elementsNr );
this.dataTagsChart .push(this.attributesNr );
while (this.dataElementsChart .length > 0) {
this.dataElementsChart .pop();
}
const elements = parseInt(this.elementsNr , 10) –
parseInt (this.childElementsNr , 10);
this.dataElementsChart .push(elements .toString ());
this.dataElementsChart .push(this.childElementsNr );
}

32
În cadrul aceste i componente sunt afișate, de asemenea , două grafice de tip plăcintă cu
informații privind numărul de elemente comparat cu numărul de atribute, respectiv numărul de
elemente comparat cu numărul de elemente care apar ca și copii. Crearea graficelor este realizată
cu elemente de interfață importate din modulul ng2-charts. Metoda initializePieCharts()
repopulează aceste grafice la fiecare selectare a unui document XML cu valorile curente.
Pentru salvarea rapoartelor pe mașina locală a clientului, este utilizată clasa FileSaver, ce
oferă o implementare standard pentru această sarcină .
getPdfFile () {
this.filesRetrieveService .retrievePdfFile (this.currentFile ).subscribe (
file => {
const blob = new Blob([file], { type: 'application/pdf' });
const fileName = this.currentFile .replace('xml', 'pdf');
FileSaver .saveAs(blob, fileName );
});
}

Metoda getPdfFile() apelează serviciul responsabil cu preluarea raportului pdf cu statistici
de la aplicația server , acesta fiind returnat sub formă de șir de octeți și împachetat într -un blob
(binary large object) cu tipul specificat application/pdf . În final, prin apelul FileSaver.saveAs(blob,
fileName) , acesta este salvat local cu numele specificat.
this.pdfRetrieveUrl = 'http://localhost:8080/api/statistics/pdf' ;

public retrievePdfFile (file: string): Observable <any> {
const params = new HttpParams ().set('fileName' , file);
return this .httpClient .get(this.pdfRetrieveUrl , {params, responseType :
'arraybuffer' });
}

Metoda retrievePdfFile() trimite o cerere HTTP de tip GET la adresa resursei asignate
creării raportului , cu numele fișierului XML setat ca parametru în cadrul cererii. La fel ca și restul
metodelor din cadrul serviciilor implementate în aplicație , răspunsul este împachetat într -un
Observable.

33
Concluzii
În capitolele precedente , au fos t prezentate tehnologiile utilizate în cadrul dezvoltării
aplicației , arhitecturile adoptate , precum și detalii de implementare . De asemenea , un scurt manual
de utilizare și perspective de îmbunătățire au fost incluse în lucrare.
Separarea interfeței de partea de logică business prin implementarea a două aplicații
distincte , prima pe parte de client dezvoltată în Angular și TypeScript , iar a doua pe partea de
server utilizând Spring Boot și Java , permite un nivel ridicat de flexibilitate , modificările aduse
unei părți având un impact minim asupra celeilalte părți.
Aplicația dezvoltată oferă funcționalități de încărcare și validare a fișierelor XML , de
analiză a structurii fișierelor și de generare de rapoarte cu date statistice privind structura lor.
Astfel, aplicația est e orientată mai mult pe analiza de fișiere decât pe editarea lor , această funcție
din urmă fiind însă propusă în capitolul precedent ca idee de îmbunătățire pe viitor. De asemenea ,
utilitatea principal ă a aplicației o face să fie destinată unui grup mai tehnic de utilizatori , putând
totuși să fie utilizată de oricine și ca instrument de învățare în ceea ce privește meta -limbajele de
marcare.
Funcționalități de editare a documentelor
La momentul actual, există câteva situații în cadrul aplicației ce necesită o rezolvare
independentă din partea utilizatorulu i, ca de exemplu : semnalarea unei erori sintactice sau de
validare contra unui set de reguli la încărcarea unui document, necesitatea modificării unor valori
etc. Pentru aceste cazuri, corectarea sau modificarea structurii documentelor trebuie realizată în tr-
un editor separat, necesitând de asemenea reîncărcarea documentelor în aplicație. Astfel, o
îmbunătățire a experienței utilizatorului ar consta în implementarea unor funcționalități care să
ofere posibilitatea editării documentelor direct în aplicație ș i revalidarea acestora în mod automat
după fiecare editare.
Din punct de vedere al implementării, procesarea DOM din cadrul Apache Xerces oferă și
metode pentru adăugarea sau ștergerea unor noduri specifice din arborele asociat documentului,
precum createElement() , createAttribute() , insertBefore() , removeChild() .

34
Sistem de înregistrare, autentificare și gestiune a documentelor
O altă îmbunătățire interesantă ar fi implementarea unui sistem de înregistrare și
autentificare opțional, utilizatorii având astfel posibilitatea creării unui portofoliu personal cu
documente încărcate și statistici după autentificare, pe care să le poată vizualiza și la accesări
viitoare ale aplicației. Pentru partea de înregistrare și autentificare, Spring S ecurity oferă
funcționalități ce pot fi incluse și adaptate cu ușurință la orice aplicație dezvoltată în Java. Crearea
unui portofoliu cu statistici și documente încărcate implică dezvoltarea unor funcționalități de
persistare a acestora într -o bază de dat e.
Având în vedere importanța prelucrării volumelo r mari de date transmise în mod continuu
în spațiul virtual , consider că soluția propusă , momentan capabilă de a analiza în mod optim fișiere
de dimensiuni relativ mici , poate reprezenta un punct de pornire pentru dezvoltarea de aplicații
web moderne , orientate pe analiza structurii fișierelor ce sunt utilizate la stocarea și transmiterea
datelor pe web .

35
Bibliografie
[1] Frăsinaru, C. (2005). Curs practic de Java.
https://profs.info.uaic.ro/~acf/java/Cristian_Frasinaru -Curs_practic_de_Java.pdf
[2] Friesen, J. (2019). Java XML and JSON: Document Processing for Java SE. apress.
[3] Gorbaty, S., Wang, X., Billimoria, H., & Brossard, J. (n.d.). XXE defence(les)s in JDK XML parsers.
https://paper.seebu g.org/papers/Security%20Conf/Blackhat/2015/us -15-Wang -FileCry -The-New -Age-
Of-XXE-java-wp.pdf
[4] Mlynkova, I., Toman, K., & Pokorny, J. (2006). Statistical Analysis of Real XML Data.
https://www.cs.cas.cz/semweb/download/06 -05-mlynkova -toman -pokorny.pdf
[5] Sabin, B. (2006). Tehnologii XML. Polirom.
https://profs.info.uaic.ro/~busaco/teach/courses/web/presentations/Sabin_Buraga -Tehnologii_XML.pdf
[6] Taghva, K., Cartright, M., & Borsack, J. (n.d.). An Efficient Tool for XML Data Preparation.
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.81.484&rep=rep1&type=pdf
[7] Walls, C. (2016). Spring Boot in Action. Manning Publications Co.
[8] Angul ar – https://angular.io/docs (consultat la 04.2020)
[9] Bootstrap – https://getb ootstrap.com/docs/4.5/getting -started/introduction/ (consultat la 04.2020)
[10] Restful API – https://restfulapi.net/ (consultat la 02.2020)
[11] Design Patterns – https://refactoring.guru/design -patterns/java (consultat la 03.2020)
[12] Spring Framework – https://spring.io/guides (consultat la 02.2020)
[13] TypeScrip t – https://www.typescriptlang.org/docs/home.html (consultat la 04.2020)
[14] Apa che Xerces – http://xerces.apache.org/xerces2 -j/ (consultat la 01.2020)

36
Anexa 1 – Manual de utilizare
Pagina Home
Această pagină este punctul de intrare în aplicație, oferind un rezumat al celorlalte pagini
și al funcționalităților oferite pentru rezolvarea problemei descrise.

Figura 6 – Pagina Home a aplicației client

Pagina Uploads
În această pagină sunt încărcate și validate fișierele XML. Interfața oferă trei butoane
pentru selectarea modului de validare al fișierul ui: corectitudinea sintactică, validarea contra unui
set de reguli definit într -un document XSD sau validarea contra unui document DTD, ultimele
două cuprinzând, de asemenea , și verificarea sintaxei. Pentru validări ce utilizează fișiere cu reguli,
sunt pr ezente două secțiuni de încărcare, atât pentru fișierul de validare cât și pentru cel XML.
Pentru cazurile eronate de utilizare, cum ar fi încărcarea unui tip incorect de fișier,
încercarea de a valida un document XML contra unui document XSD ce nu este r eferit cu
noNamespaceSchemaLocation , mesaje de eroare corespunzătoare sunt trimise de aplicația server
și afișate în pagină.

37

Figura 7 – Mesaj de eroare la încărcarea unui document PNG
Pe lângă opțiunea de încărcare a fișierelor de pe sistemul local, este oferită și opțiunea de
încărcare de la o adresă url, verificându -se de asemenea la validare și corectitudinea adresei.
Pentru valida rea unui fișier XML contra unui set de reguli definit într -un XSD sau DTD,
se încarcă fișierul de validare și ulterior fișierul XML, orice eroare de sintaxă sau de validare fiind
de asemenea afișată. Totodată, sunt semnalate și posibilele erori de sintaxă prezente în fișierele de
validare.

Figura 8 – Mesaj de eroare la validarea unui XML cu un XSD
În exemplul din imagine, fișierul XSD a fost încărcat cu succes, iar pentru fișierul XML, o
eroare de validare a fost afișată din pricina prezenței unui tag nedefinit în XSD.

38
Pagina Statistics
Afișarea documentelor XML încărcate și validate cu succes, precum și modurile de
extragere a informațiilor din documente sunt realizate în această pagină. Pentru fiecare document,
pe lângă e lementele de interfață standard ce pot fi utilizate, sunt afișate date specifice precum
numărul de elemente, numărul de atribute sau lungimea totală a conținutului text.
Pentru căutarea numărului de apariții al unui anumit element sau atribut, sunt oferit e în
interfață câmpuri text pentru preluarea denumirii elementului sau atributului. Căutarea se face în
fișierul curent selectat sau în toate fișierele încărcate, în cazul bifării opțiunii Search all files .

Figura 9 – Căutarea nr. de apariții pt. elemente/atribute
Alte date ce pot fi extrase dintr -un document XML sunt numărul de elemente și de atribute
aflate la un anumit nivel de adâncime în structura documentului, nivelul maxim fiind de asemenea
afișat la selectar ea unui document odată cu celelalte informații specifice. Totodată, raportul pdf cu
statistici generate pentru un anumit fișier cuprinde și informații privind numărul de elemente și
atribute aflate la fiecare nivel de adâncime.
Pagina prezintă de asemenea opțiuni de a extrage informații mai detaliate pentru elemente
și atribute ce conțin valori numerice, câteva exemple fiind: valorile minime și maxime, suma,
media, deviația standard.
Pentru un mod de extragere a informațiilor ce permite o mai mare flexibi litate din partea
utilizatorului, este pus la dispoziție un câmp text pentru preluarea expresiilor XPath.

39

Figura 10 – Extragerea datelor pentru valori numerice
Cele două grafice de tip placintă, ce afișează date pentru numărul de elemente comparat cu
numărul de atribute, respectiv numărul de elemente comparat cu numărul de elemente copil, sunt
adaptate automat în funcție de datele extrase de la documentul XML selectat.

Figura 11 – Pie charts cu date extrase din documentul XML

40

Figura 12 – Extragere nr noduri la anumite adâncimi
Extragerea numărului de elemente/atribute aflate la o anumită adâncime se realizează într-
o manieră similară , cu specificarea nivelului de adâncime în câmpuri text . Pentru evitarea erorilor ,
în cazul specificării unui număr mai mare decât adâncimea maximă sau a unui conținut invalid
(cum ar fi șir de caractere) , conținutul din câmp este șters automat.

Figura 13 – Raport pdf cu statistici
Raportul pdf generat pe baza fișierului XML curent din interfață conține date mai detaliate
privind elementele, atributele , nivelurile de adâncime și calcule pentru valori numerice extrase.

Similar Posts