{"id":893,"date":"2016-05-17T10:00:00","date_gmt":"2016-05-17T08:00:00","guid":{"rendered":"https:\/\/blogs.autodesk.com\/villagebim\/2016\/05\/connecter-dynamo-a-microsoft-access.html"},"modified":"2021-02-09T21:58:03","modified_gmt":"2021-02-09T19:58:03","slug":"connecter-dynamo-a-microsoft-access","status":"publish","type":"post","link":"https:\/\/blogs.autodesk.com\/villagebim\/2016\/05\/connecter-dynamo-a-microsoft-access.html","title":{"rendered":"Connecter Dynamo \u00e0 Microsoft Access"},"content":{"rendered":"<p><a href=\"http:\/\/villagebim.typepad.com\/.a\/6a015391e15a28970b01bb08d493c6970d-pi\"><img loading=\"lazy\" decoding=\"async\" alt=\"image\" border=\"0\" height=\"195\" src=\"https:\/\/blogs.autodesk.com\/villagebim\/wp-content\/uploads\/sites\/154\/2021\/02\/img_6022e94b93bef.png\" style=\"padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px;margin-left: auto;margin-right: auto;background-image: none\" title=\"image\" width=\"454\" \/><\/a><\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p style=\"text-align: justify\">Encore une fa\u00e7on d\u2019augmenter les possibilit\u00e9s de Dynamo est de le connecter \u00e0 une base de donn\u00e9es de type Microsoft Access. C\u2019est ce que propose mon coll\u00e8gue Italien <a href=\"http:\/\/blogs.autodesk.com\/dalbiminpoi\/author\/stefanotoparini\/\">Stefano Toparini<\/a> sur son blog&#160; <a href=\"http:\/\/blogs.autodesk.com\/dalbiminpoi\/\">dal BIM in poi.\u2026<\/a><\/p>\n<p style=\"text-align: justify\">Stefano, \u00e0 partir de <a href=\"http:\/\/www.autodesk.com\/products\/dynamo-studio\/overview\">Dynamo Studio<\/a> (et non <a href=\"http:\/\/dynamobim.org\/\">Dynamo for Revit<\/a>) et du package Lunchbox, nous montre qu\u2019il est possible de lire une base de donn\u00e9es Access. Pour r\u00e9aliser cet exploit, il a du cr\u00e9er son propre n\u0153ud en langage Python.<\/p>\n<p style=\"text-align: justify\">Je vais vous en faire l\u2019explication (exercice difficile mais \u00e0 c\u0153ur volontaire\u2026).<\/p>\n<p style=\"text-align: justify\">Le n\u0153ud s\u2019appelle \u201c<em><strong>ReadAccessTable<\/strong><\/em>\u201d. Pour d\u00e9couvrir le code Python, double cliquer sur le n\u0153ud, puis clic droit \u201c<em><strong>Edit<\/strong><\/em>\u201d sur le n\u0153ud <em>\u201c<strong>python script<\/strong><\/em>\u201d.<\/p>\n<p><a href=\"http:\/\/villagebim.typepad.com\/.a\/6a015391e15a28970b01bb08d493d0970d-pi\"><img loading=\"lazy\" decoding=\"async\" alt=\"image\" border=\"0\" height=\"868\" src=\"https:\/\/blogs.autodesk.com\/villagebim\/wp-content\/uploads\/sites\/154\/2021\/02\/img_6022e94d6918c.png\" style=\"padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px;margin-left: auto;margin-right: auto;background-image: none\" title=\"image\" width=\"454\" \/><\/a><\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p style=\"text-align: justify\">Le n\u0153ud accepte trois param\u00e8tres, dont seule le premier est obligatoire:<\/p>\n<ul style=\"text-align: justify\">\n<li>Si vous entrez seulement le nom du fichier, le n\u0153ud renvoie \u00e0 la liste des tables de la base de donn\u00e9es,<\/li>\n<\/ul>\n<p><a href=\"http:\/\/villagebim.typepad.com\/.a\/6a015391e15a28970b01b7c82ff6dc970b-pi\"><img loading=\"lazy\" decoding=\"async\" alt=\"image\" border=\"0\" height=\"201\" src=\"https:\/\/blogs.autodesk.com\/villagebim\/wp-content\/uploads\/sites\/154\/2021\/02\/img_6022e94f5f68b.png\" style=\"padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px;margin-left: auto;margin-right: auto;background-image: none\" title=\"image\" width=\"454\" \/><\/a><\/p>\n<p>&#160;<\/p>\n<ul style=\"text-align: justify\">\n<li>Si vous entrez en plus le nom de la table, le n\u0153ud renvoie tous les enregistrements avec tous les champs,<\/li>\n<\/ul>\n<p>&#160;<\/p>\n<p><a href=\"http:\/\/villagebim.typepad.com\/.a\/6a015391e15a28970b01bb08d493da970d-pi\"><img loading=\"lazy\" decoding=\"async\" alt=\"image\" border=\"0\" height=\"306\" src=\"https:\/\/blogs.autodesk.com\/villagebim\/wp-content\/uploads\/sites\/154\/2021\/02\/img_6022e950d043a.png\" style=\"padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px;margin-left: auto;margin-right: auto;background-image: none\" title=\"image\" width=\"454\" \/><\/a><\/p>\n<p>&#160;<\/p>\n<ul style=\"text-align: justify\">\n<li>Si vous entrez en plus une liste de champs s\u00e9par\u00e9s par des <strong>virgules<\/strong> <strong>uniquement,<\/strong> les valeurs sont sont extraites des champs (s&#039;il y a des espaces dans les noms des champs, vous devez mettre ces noms entre crochets, par exemple. [Nom de la soci\u00e9t\u00e9]).<\/li>\n<\/ul>\n<p>&#160;<\/p>\n<p><a href=\"http:\/\/villagebim.typepad.com\/.a\/6a015391e15a28970b01bb08d493df970d-pi\"><img loading=\"lazy\" decoding=\"async\" alt=\"image\" border=\"0\" height=\"325\" src=\"https:\/\/blogs.autodesk.com\/villagebim\/wp-content\/uploads\/sites\/154\/2021\/02\/img_6022e95205174.png\" style=\"padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px;margin-left: auto;margin-right: auto;background-image: none\" title=\"image\" width=\"454\" \/><\/a><\/p>\n<p style=\"text-align: justify\">Essayons de d\u00e9tailler son code:<\/p>\n<p style=\"text-align: justify\"><strong><u>Partie Importations de modules et d\u00e9clarations :<\/u><\/strong><\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p><a href=\"http:\/\/villagebim.typepad.com\/.a\/6a015391e15a28970b01bb08d493e8970d-pi\"><img loading=\"lazy\" decoding=\"async\" alt=\"image\" border=\"0\" height=\"162\" src=\"https:\/\/blogs.autodesk.com\/villagebim\/wp-content\/uploads\/sites\/154\/2021\/02\/img_6022e9531cf87.png\" style=\"padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px;margin-left: auto;margin-right: auto;background-image: none\" title=\"image\" width=\"454\" \/><\/a><\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p style=\"text-align: justify\">Important : cette partie permet d\u2019importer la classe \u201c<em><strong>Access<\/strong><\/em>\u201d issue du module \u201c<em><strong>Microsoft.Office.Interop<\/strong><\/em>\u201d.<\/p>\n<p style=\"text-align: justify\">La ligne \u201c<strong><em>ac.Visible = False<\/em><\/strong>\u201d&#160; \u00e9vite d\u2019afficher l\u2019interface Access.<\/p>\n<p style=\"text-align: justify\">Le mot cl\u00e9 \u201c<em><strong>try<\/strong><\/em>:\u201d permet d\u2019essayer un \u201c bout de code\u201d. Si une erreur est rencontr\u00e9e, on cesse d&#039;interpr\u00e9ter le code et on passe \u00e0 l\u2019autre mot cl\u00e9 \u201c<strong>e<em>xcept<\/em><\/strong>:\u201d. De cette fa\u00e7on cela \u00e9vite de bloquer dans une boucle et d\u2019agir en fonction de l&#039;erreur qui s&#039;est produite.<\/p>\n<p style=\"text-align: justify\">Donc :<\/p>\n<p style=\"text-align: justify\">\u201c<em><strong>ac.OpenCurrentDatabase(IN[0])<\/strong>\u201d <\/em>: ouvre la base dont le chemin est contenue dans la variable\u201d<em><strong>IN[0]<\/strong>\u201d (premi\u00e8re entr\u00e9e de script python),<\/em><\/p>\n<p style=\"text-align: justify\">\u201c<em><strong>ac.Quit<\/strong><\/em>\u201d : m\u00e9thode qui permet de quitter Access.&#160; <br \/>\u201d<em><strong>sys.exit(0)<\/strong>\u201d<\/em> : sortie de Python avec le statut de sortie z\u00e9ro.<\/p>\n<p style=\"text-align: justify\">Enfin :<\/p>\n<p style=\"text-align: justify\">\u201c<em><strong>database = ac.DBEngine<\/strong><\/em>\u201d: assigne de la variable \u201c<em><strong>database<\/strong><\/em>\u201d au moteur de base de donn\u00e9es.<\/p>\n<p style=\"text-align: justify\">\u201c<strong>wrks = database.Workspaces(0)\u201d<\/strong> : alloue la variable \u201c<em><strong>wrks<\/strong><\/em> \u201d \u00e0 la collection \u201c<em><strong>Workspaces<\/strong><\/em>\u201d repr\u00e9sentant un espace de travail au sein du moteur de base de donn\u00e9es.<\/p>\n<p style=\"text-align: justify\">\u201c<em><strong>db = wrks.Databases(0<\/strong>)\u201d<\/em> : attribut de la variable \u201c<em><strong>db<\/strong><\/em> \u201c \u00e0 la collection \u201c<em><strong>Databases<\/strong><\/em>\u201d regroupant l&#039;ensemble des objets \u201c<strong>Database<\/strong>\u201d ouverts dans l&#039;objet \u201c<em><strong>Workspace<\/strong><\/em>\u201d correspondant.<\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p style=\"text-align: justify\"><strong><u>1- Partie \u201csi aucun nom de table est affect\u00e9\u201d au script python :<\/u><\/strong><\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p><a href=\"http:\/\/villagebim.typepad.com\/.a\/6a015391e15a28970b01b8d1ba5f50970c-pi\"><img loading=\"lazy\" decoding=\"async\" alt=\"image\" border=\"0\" height=\"169\" src=\"https:\/\/blogs.autodesk.com\/villagebim\/wp-content\/uploads\/sites\/154\/2021\/02\/img_6022e9553d7c7.png\" style=\"padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px;margin-left: auto;margin-right: auto;background-image: none\" title=\"image\" width=\"454\" \/><\/a><\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p style=\"text-align: justify\">\u201c<em><strong>if IN[1] == None :\u201d<\/strong> :<\/em> si la deuxi\u00e8me entr\u00e9e (\u201cNom de la table\u201d) est vide, il va faire ce qui suit sinon il saute au code situ\u00e9 en dessous de \u201c<em><strong>else<\/strong>:\u201d<\/em> (explication partie suivante).<\/p>\n<p style=\"text-align: justify\">La variable <em>\u201c<strong>ts<\/strong>\u201d<\/em> r\u00e9cup\u00e8re le nombre d&#039;objet dans la collection<em> \u201c<strong>db<\/strong>\u201d<\/em>.<\/p>\n<p style=\"text-align: justify\">\u201c<em><strong>tables<\/strong><\/em>\u201d : cr\u00e9ation d\u2019une variable vide de type tableau.<\/p>\n<p style=\"text-align: justify\">\u201c<strong>f<\/strong><em><strong>or t in db.TableDefs<\/strong> <\/em>:\u201d r\u00e9alise une boucle de t=0 jusqu\u2019au nombre d\u2019objet dans la collection<em> \u201c<strong>db<\/strong>\u201d<\/em>.<\/p>\n<p style=\"text-align: justify\">Nota : l\u2019auteur aurait pu \u00e9crire \u201c<em><strong>for t in<\/strong> <strong>ts:<\/strong><\/em>\u201d<\/p>\n<p style=\"text-align: justify\">\u201c<em><strong>if not t.Name.startswith(&#039;MSys&#039;) :<\/strong>\u201d<\/em> filtre les \u00e9l\u00e9ments dans la liste qui ne commence pas par le texte <em>&#039;MSys&#039;<\/em>. Dans le cas contraire, nous aurions ce r\u00e9sultat :<\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p><a href=\"http:\/\/villagebim.typepad.com\/.a\/6a015391e15a28970b01b8d1ba5f5b970c-pi\"><img loading=\"lazy\" decoding=\"async\" alt=\"image\" border=\"0\" height=\"539\" src=\"https:\/\/blogs.autodesk.com\/villagebim\/wp-content\/uploads\/sites\/154\/2021\/02\/img_6022e956d0dc2.png\" style=\"padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px;margin-left: auto;margin-right: auto;background-image: none\" title=\"image\" width=\"354\" \/><\/a><\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p style=\"text-align: justify\">Donc si la condition n\u2019est pas respect\u00e9e, \u201c<em><strong>tables.append(t.Name)\u201d<\/strong><\/em> permet d\u2019enregistrer dans la table la valeur \u00e0 l\u2019indice \u201c<strong><em>t<\/em><\/strong>\u201d.<\/p>\n<p style=\"text-align: justify\">\u201c<em><strong>OUT = tables<\/strong><\/em>\u201d donne comme r\u00e9sultat de la variable tableau \u201c<em><strong>tables<\/strong><\/em>\u201d comme r\u00e9sultat du script python.<\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p style=\"text-align: justify\"><strong><u>2- Partie si un nom de table est affect\u00e9&#160; :<\/u><\/strong><\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p><a href=\"http:\/\/villagebim.typepad.com\/.a\/6a015391e15a28970b01b8d1ba5f63970c-pi\"><img loading=\"lazy\" decoding=\"async\" alt=\"image\" border=\"0\" height=\"488\" src=\"https:\/\/blogs.autodesk.com\/villagebim\/wp-content\/uploads\/sites\/154\/2021\/02\/img_6022e95899287.png\" style=\"padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px;margin-left: auto;margin-right: auto;background-image: none\" title=\"image\" width=\"454\" \/><\/a><\/p>\n<p style=\"text-align: justify\">&#160;<\/p>\n<p style=\"text-align: justify\">Le \u201c<em><strong>else<\/strong>:<\/em>\u201d en d\u00e9but permet de rentrer dans cette boucle dans le cas o\u00f9 une table est affect\u00e9e.<\/p>\n<p style=\"text-align: justify\">\u201c<em><strong>if IN[2] == None :<\/strong>\u201d <\/em>: si la variable d\u2019entr\u00e9e du script phyton \u201c<strong><em>IN[2]<\/em><\/strong>\u201d n\u2019est pas attribu\u00e9e (sinon on passe au \u201c<em><strong>else :<\/strong>\u201d<\/em> suivant, voir plus loin). <br \/>&#160;&#160;&#160; \u201c<em><strong>rs = db.OpenRecordset(IN[1])<\/strong>\u201d<\/em> : la m\u00e9thode \u201c<em><strong>OpenRecordset<\/strong><\/em>\u201d assigne \u00e0 la variable \u201c<em><strong>rs<\/strong><\/em>\u201d du nom de la table de la base de donn\u00e9es. <br \/>&#160;&#160;&#160; \u201c<strong><em>fields = []<\/em><\/strong>\u201d : cr\u00e9ation d\u2019une variable \u201c<em><strong>fields<\/strong><\/em>\u201d vide de type tableau. <br \/>&#160;&#160;&#160; \u201c<em><strong>for f in rs.Fields :<\/strong>\u201d<\/em> : r\u00e9alise une boucle jusqu\u2019au nombre de champs dans la collection<em> \u201c<strong>rs<\/strong>\u201d<\/em>. <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; \u201c<em><strong>fields.append(f.Name)<\/strong>\u201d<\/em> : enregistre dans la tableau \u201c<em><strong>fields<\/strong><\/em>\u201d la valeur des champs \u00e0 l\u2019indice \u201c<strong><em>f<\/em><\/strong>\u201c. <br \/>\u201d<em><strong>else<\/strong>:<\/em> \u201c : si la variable d\u2019entr\u00e9e du script python \u201c<strong><em>IN[2]<\/em><\/strong>\u201d est attribu\u00e9e, on passe au code ci-dessous:<\/p>\n<p style=\"text-align: justify\">\u201c<em><strong>q = &#039;SELECT &#039; + IN[2] + &#039; FROM &#039; + IN[1]<\/strong>\u201d<\/em> : la variable est la concat\u00e9nation de mots (SELECT et FROM) et de la deuxi\u00e8me (nom de la table de la base de donn\u00e9es) \/ troisi\u00e8me variable (liste des valeurs) d\u2019entr\u00e9e du script python. <br \/>\u201d<strong><em>rs = db.OpenRecordset(q<\/em>)<\/strong>\u201d : la m\u00e9thode \u201c<em><strong>OpenRecordset<\/strong><\/em>\u201d qui attribue \u00e0 la variable \u201c<em><strong>rs<\/strong><\/em>\u201d du nom de la table de la base de donn\u00e9es indiqu\u00e9e par la variable \u201c<em><strong>q<\/strong><\/em>\u201d (requ\u00eate SQL). <br \/>\u201d<em><strong>fields = IN[2].split(&quot;,&quot;)<\/strong>\u201d : cr\u00e9ation d\u2019une variable \u201c<em><strong>fields<\/strong><\/em>\u201d&#160; de type tableau dans laquelle on supprime le symbole de type \u201cvirgule\u201d issue des diff\u00e9rentes donn\u00e9es.<\/em> <br \/>\u201c<strong><em>for i in range(len(fields)) :<\/em><\/strong> \u201c effectue un boucle de i=0 au nombre de champs \u201c<strong><em>(Len(Fields)<\/em><\/strong>\u201d. <br \/>\u201d<strong><em>fields[i] = fields[i].strip()<\/em><\/strong>\u201d : supprime les espaces de chaque champ.<\/p>\n<p style=\"text-align: justify\">Enfin la derni\u00e8re partie :<\/p>\n<p style=\"text-align: justify\">\u201c<strong><em>rows = []<\/em><\/strong>\u201d : cr\u00e9ation d\u2019une variable de type tableau vide (attention variable au pluriel). <br \/>\u201d<em><strong>while not rs.EOF:<\/strong><\/em>\u201d : boucle de type \u201c<em>tant que l\u2019on n\u2019est pas<\/em>\u201d balaye tous les champs jusqu\u2019a la fin du fichier &#8211; <strong>E<\/strong>nd <strong>O<\/strong>f <strong>F<\/strong>Ile. <br \/>\u201d<strong><em>row = rs.GetRows(1)<\/em><\/strong>\u201d : la m\u00e9thode \u201c<em><strong>GetRows(1)<\/strong><\/em>\u201d extrait une seule ligne de la base de donn\u00e9e et l\u2019affecte \u00e0 la variable \u201c<em><strong>row<\/strong><\/em>\u201d (en fait on effectue cette op\u00e9ration ligne par ligne).<\/p>\n<p style=\"text-align: justify\">Attention, \u201crow\u201d (au singulier) est une nouvelle variable non d\u00e9clar\u00e9e.&#160; <br \/>\u201c<em><strong>rows.append(row)<\/strong><\/em>\u201d : la m\u00e9thode \u201c<em><strong>append<\/strong><\/em>\u201d ajoute l\u2019enregistrement de la variable \u201c<em><strong>row<\/strong><\/em>\u201d dans \u00e0 la variable de type tableau \u201c<em><strong>rows<\/strong><\/em>\u201d.<\/p>\n<p style=\"text-align: justify\">\u201c<em><strong>OUT = [fields, rows]<\/strong><\/em>\u201d : en fin de boucle, nous restituons au script python les deux variables :<\/p>\n<blockquote>\n<p>&#8211; \u201c<em><strong>fields<\/strong><\/em>\u201d : les intitul\u00e9s du tableau.<\/p>\n<p>&#8211; \u201c<em><strong>rows<\/strong><\/em>\u201d : les valeurs des champs.<\/p>\n<\/blockquote>\n<p style=\"text-align: justify\">&quot;<em><strong>ac.Quit<\/strong><\/em>\u201d : m\u00e9thode qui permet de quitter Access (lib\u00e8re la m\u00e9moire).<\/p>\n<p style=\"text-align: justify\">J\u2019esp\u00e8re que j\u2019ai \u00e9t\u00e9 assez clair car comme vous avez pu le voir ce n\u2019est pas si facile \u00e0 expliquer.<\/p>\n<p style=\"text-align: justify\">Vous trouverez la totalit\u00e9 de l\u2019article de mon confr\u00e8re Italien <a href=\"http:\/\/blogs.autodesk.com\/dalbiminpoi\/2016\/03\/31\/dynamo-microsoft-access\/\">ici<\/a> avec le t\u00e9l\u00e9chargement de son exemple (en fin d\u2019article).<\/p>\n<p style=\"text-align: justify\"><strong>Bravovisimo Stefano et grazie pour ton billet.<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#160; Encore une fa\u00e7on d\u2019augmenter les possibilit\u00e9s de Dynamo est de le connecter \u00e0 une base de donn\u00e9es de type Microsoft Access. C\u2019est ce que propose mon coll\u00e8gue Italien Stefano Toparini sur son blog&#160; dal BIM in poi.\u2026 Stefano, \u00e0 partir de Dynamo Studio (et non Dynamo for Revit) et du package Lunchbox, nous montre [&hellip;]<\/p>\n","protected":false},"author":4760,"featured_media":2472,"menu_order":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[6],"tags":[1301,20,171,1302],"class_list":["post-893","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-trucs-et-astuces","tag-access","tag-autodesk","tag-dynamo","tag-stepfano","dhig-theme--light"],"acf":[],"_links":{"self":[{"href":"https:\/\/blogs.autodesk.com\/villagebim\/wp-json\/wp\/v2\/posts\/893","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.autodesk.com\/villagebim\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.autodesk.com\/villagebim\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.autodesk.com\/villagebim\/wp-json\/wp\/v2\/users\/4760"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.autodesk.com\/villagebim\/wp-json\/wp\/v2\/comments?post=893"}],"version-history":[{"count":0,"href":"https:\/\/blogs.autodesk.com\/villagebim\/wp-json\/wp\/v2\/posts\/893\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.autodesk.com\/villagebim\/wp-json\/wp\/v2\/media\/2472"}],"wp:attachment":[{"href":"https:\/\/blogs.autodesk.com\/villagebim\/wp-json\/wp\/v2\/media?parent=893"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.autodesk.com\/villagebim\/wp-json\/wp\/v2\/categories?post=893"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.autodesk.com\/villagebim\/wp-json\/wp\/v2\/tags?post=893"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}