{"id":2683,"date":"2018-01-08T12:36:26","date_gmt":"2018-01-08T12:36:26","guid":{"rendered":"http:\/\/www.colorwave.it\/blog\/?p=2683"},"modified":"2018-01-09T00:37:42","modified_gmt":"2018-01-09T00:37:42","slug":"tags-il-namespace-per-la-gestione-delle-liste-di-tags-in-un-file","status":"publish","type":"post","link":"https:\/\/www.colorwave.it\/blog\/framework\/tags-il-namespace-per-la-gestione-delle-liste-di-tags-in-un-file\/admin\/2018\/01\/","title":{"rendered":"TAGS: il namespace per la gestione delle liste di tags in un file"},"content":{"rendered":"<p>Il namespace TAGS contiene le classi base per la definizione di tags e liste di tags: TAG e TAG_list.<\/p>\n<p>Il file <a href=\"https:\/\/en.wikipedia.org\/wiki\/TIFF\">TIFF<\/a> (acronimo di <em>Tagged Image File Format<\/em>) permette l&#8217;accesso alle diverse informazioni salvate attraverso l&#8217;indicazione del tag,\u00a0 un valore numerico che le identifica;<\/p>\n<p>Le classi contenute nel namespace TAGS svolgono un compito analogo,\u00a0 permettendo la ricerca in un indice di tag (TAG_list) di informazioni di qualunque genere; La differenza sostanziale \u00e8 che gli indici sono in forma alfanumerica e che le informazioni corrispondono a classi e strutture C++ memorizzbili su file; Di seguito presenteremo in dettaglio le classi TAG e TAG_list e le specifiche di costruzione delle classi di tipo TAG;<\/p>\n<hr \/>\n<p><span style=\"color: #0000ff;\">Avvertenza:<em>\u00a0<\/em><\/span><em><span style=\"color: #0000ff;\"><span style=\"color: #000000;\">in questo articolo \u00e8 definito <span style=\"color: #800000;\">tag<\/span> una qualunque istanza di una classe derivata da TAG, cio\u00e8 che possiede l&#8217;interfaccia TAG.\u00a0 definiremo <span style=\"color: #800000;\">tag_list<\/span> una qualunque istanza di una classe TAG_list.<\/span><\/span><\/em><\/p>\n<hr \/>\n<h4>TAG<\/h4>\n<p>Un TAG \u00e8 una classe contenitore di dati; tutte le classi derivate da TAG sono dotate di un identificatore (definibile attraverso la funzione <span style=\"color: #800000;\">Set_id<\/span>) che \u00e8 specifico delle stesse; ad esempio tutte le istanze di classe DocumentSize hanno lo stesso identificatore.<\/p>\n<p>Ciascuna istanza di una classe derivata da TAG \u00e8 dotata di nome, definito attraverso la funzione <em><span style=\"color: #800000;\">Set_name<\/span><\/em>; Il nome dell&#8217;istanza \u00e8 utilizzato per ricercare la stessa in una lista di TAG: per default, in assenza di definizione del nome, il nome \u00e8 posto uguale all&#8217;identificatore della classe, ma in una lista \u00e8 inseribile un solo tag per ciascun nome; quindi se si inseriscono pi\u00f9 tag in una tag_list, ciascun avr\u00e0 un nome unico, indipendentemente dal tipo.<\/p>\n<pre class=\"lang:default decode:true\" title=\"La classe TAG\" style=\"padding-left: 90px;\">class AFX_EXT_CLASS TAG\r\n{\r\n   friend class TAG_list;\r\n   public:\r\n\tTAG();\r\n\t~TAG();\r\n\r\n        bool Set_id(STRING id);\r\n        STRING Get_id();\r\n\r\n\tbool Set_name(STRING id);\r\n\tSTRING  Get_name();\r\n\r\n\tbool Register_tag();\r\n\r\n\tstatic TAG *New_tag(STRING id);\r\n\r\n\tstatic bool  Registered_tag(STRING id);\r\n\r\n\tstatic void Destroy_registered_tags();\r\n\r\n\t__use_tag_funcs\r\n\t__use_private_struct\r\n\r\n\tUBYTE *Alloc_buffer(int bsize);\r\n\tUBYTE *Get_buffer(int *bsize);\r\n\r\n};\r\n<\/pre>\n<p><strong>Set_id()<\/strong> : assegna un id di identificazione del tipo di tag; ogni classe tag possiede un idunivoco; in pratica non si usa direttamente questa funzione, si utilizza la macro\u00a0<em>_tag_register<\/em> che descriveremo fra poco, e che, inserita nel costruttore di una classe derivata da TAG, la rende disponibile per il salvataggio e richiamo da file;<\/p>\n<p><strong>Get_id()<\/strong> : rimanda l&#8217;identificatore della classe; I&#8217;id della classe pu\u00f2 essere usato per verificare la sua registrazione dell&#8217;applicazione.<\/p>\n<p><strong>Set_name() e Get_name():\u00a0<\/strong>le due funzioni definiscono e rimandano il nome assegnato ad una tag istanziata; la ricerca del tag in una tag_list \u00e8 effettuata attraverso il nome assegnato.<\/p>\n<p><strong>Register_tag(): <\/strong>Per essere inseribile in una tag_list la classe TAG deve essere appositamente registrata nell&#8217;applicazione; la registrazione permette il riconoscimento automatico dei tag in fase di scrittura e lettura file ( oltre ad altri automatismi la cui conoscenza non \u00e8 per ora necessaria); Il modo migliore per effettuare la registrazione \u00e8 l&#8217;inserimento nel costruttore della classe della macro\u00a0\u00a0<em><span style=\"color: #800000;\">_tag_register\u00a0\u00a0<\/span><\/em>che effettua sia l&#8217;assegnazione dell&#8217;identificatore della classe, sia la sua registrazione (si consiglia di inserire questa macro alla fine del codice del costruttore della classe).<\/p>\n<p>La classe TAG contiene un gruppo di funzioni statiche che istanziano\u00a0 TAG registrati attraverso l&#8217;id, o controllano che un particolare id corrisponda ad un tipo di TAG registrato:<\/p>\n<p><strong>\u00a0New_tag(STRING id)\u00a0<\/strong>: istanzia un TAG dato il suo id; se l&#8217;id non corrisponde ad un TAG registrato, rimanda 0; poich\u00e8 viene istanziata una classe,\u00a0 il suo rilascio pu\u00f2 essere fatto in due modi: se non utilizzato altrimenti usare <em>delete;<\/em> se invece il tag \u00e8 inserito in una tag_list, il distruttore della stessa rilascer\u00e0 tutti i tag contenuti;<\/p>\n<p><strong>Registered_tag(STRING id)<\/strong> : controlla che l&#8217;id corrisponda ad un TAG registrato, ed in questo caso rimanda true;<\/p>\n<p><strong>Destroy_registered_tags();\u00a0<\/strong>distrugge la lista dei TAG registrati in precedenza nel software;\u00a0 la funzione \u00e8 usata solo internamente dalle classi del namespace TAGS e non deve mai essere usata fuori da questo contesto.<\/p>\n<p><em><strong>Funzioni e metodi virtuali della classe<\/strong><\/em><\/p>\n<p>la macro __use_tag_funcs \u00e8 cos\u00ec definita:<\/p>\n<pre class=\"lang:default decode:true \">#define __use_tag_funcs  __use_file_io virtual TAG  *New(); \r\n<\/pre>\n<p>serve a dichiarare nel corpo di definizione delle classi derivate da TAG un gruppo di funzioni virtuali <em>che devono essere sempre definite per ciascuna nuova classe:<\/em><\/p>\n<p><strong>New()\u00a0<\/strong> \u00e8 una funzione che istanzia la classe, rimandandone il puntatore<\/p>\n<p><strong>Read(DataFile *fd)\u00a0 e Write(DataFile *fd)<\/strong>, sono le solite funzioni standard per effettuare la lettura e scrittura di classi su un file\u00a0 (ricordiamo che praticamente su tutte le classi di Colibri che devono essere salvate\/lette su file sono definite le due funzioni e la classe DataFile rende disponibili la\u00a0 scrittura e lettura sul file).<\/p>\n<p>Le funzioni\u00a0<strong>Alloc_buffer<\/strong> e <strong>Get_buffer<\/strong> sono\u00a0 usate solo dalla classe TAG_list, e non \u00e8 necessario (per ora) conoscerne l&#8217;utilizzo;<\/p>\n<p><!--nextpage-->La classe TAG_list \u00e8 il gestore delle liste di tag assegnate; \u00e8 una struttura indice che pu\u00f2 essere memorizzata su file; le tag_list in genere sono definite all&#8217;interno di altre classi: ad esempio la classe DOCUMENT contiene una\u00a0 tag_list nella quale sono memorizzate tutte i tag delle propriet\u00e0;<\/p>\n<p>Il vantaggio maggiore nell&#8217;utilizzo delle tag_list \u00e8 la leggibilit\u00e0 dei file che le contengono da parte di versioni precedenti di Colibri (a partire dalla revisione 7 in poi..); In questo caso i tag eventualmente non interpretabili dalle versioni precedenti del software rimangono inalterati e accessibili alle versioni successive anche dopo salvataggio.<\/p>\n<hr \/>\n<p><span style=\"color: #0000ff;\"><em>Una interessante caratteristica<\/em><strong><em>:<\/em><\/strong><\/span>\u00a0La classe <em>TAG_list<\/em> deriva da\u00a0<em>TAG<\/em>: questo significa che una tag_list pu\u00f2 contenere\u00a0 altre tag_list: in altre parole, \u00e8 possibile generare e gestire tag_list di tag_list a pi\u00f9 livelli-.<\/p>\n<hr \/>\n<pre class=\"lang:default decode:true\" title=\"La classe TAG_list\">class AFX_EXT_CLASS TAG_list : public TAG\r\n\t{\r\n\tpublic:\r\n\t\tTAG_list();\r\n\t\t~TAG_list();\r\n\r\n\t\tTAG *Create(TAG &amp;tag, STRING name);\r\n\r\n\t\tbool Add_tag(TAG *tag);\r\n\r\n\t\tTAG * Get_tag(STRING id);\r\n\r\n\t\tTAG * Get_tag(TAG &amp;tag);\r\n\r\n\t\tFILEPTR Get_file_end_pos();\r\n\r\n\t\t__use_tag_funcs\r\n\t\t__use_private_struct\r\n\t};<\/pre>\n<p><b>Create(TAG &amp;tag, STRING name)<\/b><br \/>\nla funzione genera ed inserisce nella lista un TAG del quale e\u2019 fornita La classe base, se la stessa \u00e9 stata registrata in precedenza; in caso contrario rimanda 0.Il secondo parametri \u00e8 il nome proprio da assegnare alll&#8217;istanza generata;<\/p>\n<p>ad esempio:<\/p>\n<pre class=\"lang:default decode:true\">TAG_list list\r\n........\r\n......\r\nDocumentSize prot;\r\nDocumentSize *sz=list.Create(prot, L\"my_name\");\r\nif (sz)\r\n{\r\n.....\r\n}\r\n<\/pre>\n<p>DocumentSize \u00e8 una classe TAG definita registrata nel software; vedremo in un esempio di definizione di una classe che usa le tag_list che \u00e8 possibile utilizzare delle macro specifiche per semplificare la scrittura del codice.<\/p>\n<p>N.B. Poich\u00e9 una tag_list contenere un solo tag per ogni nome, \u00a0a un secondo tentativo la \u00a0funzione Create rimander\u00e0 0.<\/p>\n<p><b>TAG * Get_tag(STRING name)<\/b><\/p>\n<p>Rimanda il tag della lista dato il suo nome (vedi la funzione Set_name()..); se non presente alcun tag con il nome passato, rimanda 0.<\/p>\n<p><b>le funzioni virtuali<\/b><\/p>\n<p>La TAG_list, derivando da TAG , possiede anche \u00a0le funzioni New, Read e Write per generare una nuova istanza, leggere e scrivere su file; la dichiarazione delle funzioni \u00e8 data attraverso la macro\u00a0<span style=\"color: #800000;\">__use_tag_funcs, <span style=\"color: #000000;\">scritta alla fine della struttura della classe.<\/span><\/span><\/p>\n<p><b>FILEPTR Get_file_end_pos()<\/b><\/p>\n<p>La funzione rimanda la posizione \u00a0dell\u2019ultimo byte della classe l\u2019ultima volta che \u00e8 stata scritta o letta nel file; vedremo in un successivo articolo le ragioni di esistenza di questa funzione; il suo valore \u00e8 mantenuto aggiornato dalle funzioni Read e Write della classe.<\/p>\n<!--nextpage-->\n<p>Trasformare una qualunque classe precedente in tag \u00e8 molto semplice; consideriamo il caso della classe <em>DocumentSize<\/em>, in uso da molti anni in Colibr\u00ec; nella dichiarazione della classe DocumentSize (DocumentSize.h) \u00e9 stato sufficiente affermare la sua discendenza da <em>TAG<\/em>\u00a0 ed aggiungere alla fine la macro\u00a0 <em>__use_tag_funcs.<\/em><\/p>\n<pre class=\"lang:default decode:true\" title=\"un esempio di classe derivata da TAG: DocumentSize\">class AFX_EXT_CLASS DocumentSize :public TAGS::TAG\r\n\t{\r\n\tpublic:\r\n\t\tDocumentSize();\r\n\t\t~DocumentSize();\r\n\t        bool SetPixelSize(int px, int py);\r\n\t\tbool SetSize(float dx, float dy, int um = unit_default);\r\n\t\tbool GetSize(float *dx, float *dy, int um = unit_default);\r\n\t\tbool GetPixelSize(int *dx, int *dy);\r\n\t\tDOC_AREA *Area();\r\n\t\tbool GetResolutions(float *resx, float *resy, int um = unit_default);\r\n\t\tint GetNearX(float x);\r\n\t\tint GetNearY(float y);\r\n\t\tbool GetNearPixel(PointF p_mm, Point *pxl);\r\n\t\tbool GetPixelPos(Point pxl, PointF *fp, int um = unit_default);\r\n\t\t\\details le dimensioni dei pixel sono l'inverso delle risoluzioni h e v\r\n\t\tbool GetPixelSize_mm(PointF *px_size);\r\n\t\tbool Valid();\r\n\t\tbool Rotate(float angle);\r\n\t\tbool operator == (DocumentSize &amp;sz);\r\n&gt;\r\n\t\t__use_tag_funcs\r\n\t\t__use_private_struct\r\n\t};<\/pre>\n<p>La dichiarazione <span style=\"color: #ff0000;\"><span style=\"color: #a60053;\"><span class=\"crayon-o\">:<\/span><span class=\"crayon-m\">public<\/span> <span class=\"crayon-v\">TAGS<\/span><span class=\"crayon-o\">::<\/span><\/span><span class=\"crayon-e\"><span style=\"color: #a60053;\">TAG<\/span> <span style=\"color: #000000;\">indica la presenza\u00a0<span style=\"color: #000000;\">dell&#8217;interfaccia TAG.\u00a0\u00a0<\/span><\/span><\/span><\/span>La macro\u00a0<span style=\"color: #a60053;\">__use_tag_funcs<span style=\"color: #000000;\"> posta alla fine della classe indica la presenza delle funzioni virtuali <span style=\"color: #a60053;\">Read, Write e New<\/span>, che dovranno essere scritte nel file sorgente cpp della classe;<\/span><\/span><\/p>\n<p><strong>Modifiche nel file DocumenSize.cpp:\u00a0<\/strong>Nella funzione del costruttore \u00e8 stata aggiunta la macro <em><span style=\"color: #800000;\">_tag_register\u00a0<\/span> <\/em>per la registrazione della classe nell&#8217;applicazione; la stringa, che\u00a0 definisce l&#8217;id assegnato, pu\u00f2 essere una qualunque sequenza alfanumerica, ma \u00e8 opportuno assegnargli un valore mnemonico;<\/p>\n<pre class=\"lang:default decode:true\" title=\"Costruttore di DocumentSize\">\tDocumentSize::DocumentSize()\r\n\t{\r\n  \t  $_init\r\n\t  _tag_register(L\"DocSize\");\r\n\t}\r\n<\/pre>\n<p><strong>Aggiunta delle funzioni virtuali:\u00a0<\/strong> le funzioni Read e Write erano gi\u00e0 presenti in DocSize, e non sono state modificate; La funzione New \u00e8 stata aggiunta mediante una macro in testa al codice sorgente. Di seguito si riporta il frammento di codice relativo alle due funzioni:<\/p>\n<pre class=\"lang:default decode:true\" title=\"Le funzioni virtuali di TAG\">\tBEGIN_READ\r\n\t{\r\n\t\tfd-&gt;Read(&amp;_$str-&gt;um);\r\n\t\tfd-&gt;Read(&amp;_$str-&gt;area.dx);\r\n\t\tfd-&gt;Read(&amp;_$str-&gt;area.dy);\r\n\t\tfd-&gt;Read(&amp;_$str-&gt;area.dx_mm);\r\n\t\tfd-&gt;Read(&amp;_$str-&gt;area.dy_mm);\r\n\t\t_calc_resolution(_$str);\r\n\t}\r\n\tEND_READ\r\n\tBEGIN_WRITE\r\n\t{\r\n\t        fd-&gt;Write(_$str-&gt;um);\r\n\t        fd-&gt;Write(_$str-&gt;area.dx);\r\n\t        fd-&gt;Write(_$str-&gt;area.dy);\r\n\t        fd-&gt;Write(_$str-&gt;area.dx_mm);\r\n\t        fd-&gt;Write(_$str-&gt;area.dy_mm);\r\n\t}\r\n\tBEGIN_WRITE\r\n\r\n\t\r\n<\/pre>\n<p>Le macro<em><span style=\"color: #800000;\"> BEGIN_READ<\/span> .. <span style=\"color: #800000;\">END_READ<\/span><\/em> e\u00a0<span style=\"color: #800000;\">BEGIN_WRITE<\/span> .. <span style=\"color: #800000;\">END_WRITE<\/span> corrispondono alle classiche funzioni di lettura e scrittura della classe su file, e si rimanda all&#8217;articolo specifico sulla progettazione delle classi di Colibri.<\/p>\n<p>La macro <span style=\"color: #800000;\">_new_tag_func <\/span>\u00e8 stata inserita dopo il blocco di dichiarazioni posto\u00a0 in testa al file DocumentSize.cpp e definisce la funzione New() della classe<\/p>\n<pre class=\"lang:default decode:true\" title=\"blocco delle dichiarazioni revisione, nomi classe e struttura\">#define CURRENT_REVISION 2\t\t\t\t\t\r\n#define CLASS_NAME_STR    DocumentSize_STR\t\r\n#define CLASS     DocumentSize \r\n\r\n__new_tag_func\r\n\r\n<\/pre>\n<p>Con queste modifiche la classe potr\u00e0 ora essere inserita in una tag_list; notare che le modifiche non ne hanno alterato l&#8217;utilizzabilit\u00e0 con i precedenti metodi, hanno per\u00f2 \u00a0aggiunto le nuove funzionalit\u00e0 richieste per l&#8217;utilizzo come tag.<\/p>\n<p><!--nextpage-->Come abbiamo visto, le TAG_list gestiscono un indice di classi TAG e possono essere inserite ovunque all&#8217;interno di un file, che pu\u00f2 contenerne pi\u00f9 di una; L&#8217;esempio che segue mostra una classe generica <em>myclass <\/em>la cui dichiarazione parziale \u00e8 la seguente:<\/p>\n<pre class=\"lang:default decode:true \" title=\"un generico uso della classe TAG_list\">class myclass\r\n{\r\n        #define dsize_id L\"DocumentSize\"   \/\/ idi assegnato alla classe\r\n\r\n\tmyclass()\r\n\t{\r\n\t\t__select_tag_list(tags)\r\n\t\t__declare_tag(DocumentSize, dsize_id)\r\n\t}\r\n\r\n\t~myclass()\r\n\t{\r\n\r\n\t}\r\n\r\n\tbool Write(DataFile *fd)\r\n\t{\r\n\t\treturn tags.Write(fd);\r\n\t}\r\n\r\n\tbool Read(DataFile *fd)\r\n\t{\r\n\t\treturn tags.Read(fd);\r\n\t}\r\n\r\n\tvoid generic_func()\r\n\t{\r\n\t\t__select_tag_list(tags)\r\n\t\t( (DocumentSize *)__get_tag(dsize_id))-&gt;SetSize(1200, 2000, unit_mm);\r\n\t\t......\r\n\r\n\t}\r\n\t\r\n\tTAG_list tags;\r\n};<\/pre>\n<p>La classe di esempio contiene solo una tag_list e nel costruttore della classe sono state utilizzate due macro:<\/p>\n<p><span style=\"color: #800000;\">__select_tag_list<\/span>\u00a0utilizzata per selezionare la lista e renderla utilizzabile dalle macro\u00a0 <em>__declare_tag<\/em> che seguono<\/p>\n<p><span style=\"color: #800000;\">__declare_tag\u00a0<\/span> aggiunge una istanza della classe <em>DocumentSize<\/em> alla lista; se si dovranno inserire pi\u00f9 tag, baster\u00e0 riutilizzare la macro pi\u00f9 volte (non c&#8217;\u00e8 limite al numero di tag inseribili nella lista). Alla fine delle operazioni, avremo generato una lista di tag utilizzabili per la lettura\/modifica; se in versioni successive della classe saranno aggiunti nuovi TAG, non sar\u00e0 necessario ridefinire le funzioni di scrittura e lettura da file, poich\u00e9 le operazioni saranno completamente gestite dalle funzioni Read e Write della TAG_list.<\/p>\n<p>Nella funzione di esempio <i>generic_func<\/i> \u00e8 mostrato l\u2019uso della funzione della classe DocumentSize::SetSize per definire\u00a0\u00a0una dimensione in mm. Come al solito \u00e8 stata usata la macro __select_tag per selezionare la lista, quindi la macro<i> __get_tag<\/i> per selezionare l\u2019elemento di nome dsize_id precedentemente allocato nella tag_list.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Il namespace TAGS contiene le classi base per la definizione di tags e liste di tags: TAG e TAG_list. Il file TIFF (acronimo di Tagged Image File Format) permette l&#8217;accesso alle diverse informazioni salvate attraverso l&#8217;indicazione del tag,\u00a0 un valore numerico che&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":true,"template":"","format":"aside","meta":{"_acf_changed":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"footnotes":"","_jetpack_memberships_contains_paid_content":false,"jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[24,19],"tags":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p9rwsf-Hh","jetpack_likes_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/posts\/2683"}],"collection":[{"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/comments?post=2683"}],"version-history":[{"count":32,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/posts\/2683\/revisions"}],"predecessor-version":[{"id":2716,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/posts\/2683\/revisions\/2716"}],"wp:attachment":[{"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/media?parent=2683"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/categories?post=2683"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/tags?post=2683"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}