Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Bonjour,
J'ai construit des fichiers XML via la datawindow de pb avec le template.
Pour les besoins, j'utilise des sous report, qui ont pour conséquence de me positionner des balises vide (ce qui n'est normalement pas gênant en XML je vous l'accorde).
Mais je dois supprimer certaines balises vides pour valider mon fichier xml.
Par exemple, sous l’élément "InvoiceLine", je peux retrouver n balises "Harware" qui sont vides.
J'ai bien essayé d'utiliser "Getcontent" , "hasChilden" , et "RemoveChildElement("Harware")" , mais il ne me supprimer que le 1er élément rencontré et ne trouve pas les autres.
Donc 2 questions , :
1°) Est-il possible de ne pas positionner les balises vides en xml ?
2°) Auriez-vous une piste pour supprimer l'ensemble des éléments qui ne contiennent aucun enregistrement ?
J'espère avoir été claire ? et merci d'avance pour vos lumières,
ci dessous, un extrait de mon fichier xml avec la balise que je veux supprimer.
<InvoiceLine> <InvoiceLineNumber/> <LineCode>GROUPEMENT 1</LineCode> <FullLineDescription/> <Quantity>0</Quantity> <UnitPrice>0</UnitPrice> <LineValue>9983.11</LineValue> <LineComment/> <LineTax> <TaxCode>04</TaxCode> <TaxRate>19.60</TaxRate> <TaxValue>1956.68</TaxValue> </LineTax> <LineValueWithTax>11939.79</LineValueWithTax> <DiscountRate>0</DiscountRate> <NetUnitPrice>0</NetUnitPrice> <SpecialTax/> <Serial> </Serial> <Harware/>
PB 12.1 build 7000
Hors ligne
wazou1812 a écrit:
...
J'ai bien essayé d'utiliser "Getcontent" , "hasChilden" , et "RemoveChildElement("Harware")" , mais il ne me supprimer que le 1er élément rencontré et ne trouve pas les autres.
...
Bonjour, et avec RemoveChildElements ça donne quoi ? (attention il faut bien boucler sur tout les éléments InvoiceLine).
Hors ligne
xlat a écrit:
wazou1812 a écrit:
...
J'ai bien essayé d'utiliser "Getcontent" , "hasChilden" , et "RemoveChildElement("Harware")" , mais il ne me supprimer que le 1er élément rencontré et ne trouve pas les autres.
...Bonjour, et avec RemoveChildElements ça donne quoi ? (attention il faut bien boucler sur tout les éléments InvoiceLine).
Bonjour,
Le problème est que je veux supprimer la balise 'Harware', uniquement si elle est vide, j'ai donc fait ce bout de code, mais qui ne supprime que la 1ère balise vide 'Hardware' se trouvant sous la balise InvoiceLine.
J'ai du loupé quelque chose, mais ou ?
PBDOM_Object pbdom_obj_array[] long ll_row TRY i_PBDOM_DOCUMENT_COMPLET.GetRootElement().GetChildElement("Invoice").GetChildElement("Module").GetChildElement ("InvoiceLine").GetContent(pbdom_obj_array) For ll_row = 1 to upperbound(pbdom_obj_array[]) If i_PBDOM_DOCUMENT_COMPLET.GetRootElement().GetChildElement("Invoice").GetChildElement("Module").GetChildElement ("InvoiceLine").GetChildElement ("Harware").HasChildren() = false then End if If i_PBDOM_DOCUMENT_COMPLET.GetRootElement().GetChildElement("Invoice").GetChildElement("Module").GetChildElement ("InvoiceLine").GetChildElement ("Harware").HasChildren() = false then i_PBDOM_DOCUMENT_COMPLET.GetRootElement().GetChildElement("Invoice").GetChildElement("Module").GetChildElement ("InvoiceLine").RemoveChildElement("Harware") End if NEXT CATCH (pbdom_exception ex1) Invo_batchs.nvuf_ecriture_batchlog(" !!! Erreur sur la suppression de balise Harware (af_suppression_balise) " + ex1.getMessage() ) return -1 END TRY return 0
Si vous avez une petite idée ? Je veux bien, merci d'avance
Hors ligne
wazou1812 a écrit:
Si vous avez une petite idée ? Je veux bien, merci d'avance
J'ai brodé sur ton code comme suit (comme je ne connais pas précisément tes specs, je teste les attributs et le contenu pour savoir si "Harware" n'est pas vide) :
PBDOM_BUILDER pbdombuilder PBDOM_Document i_PBDOM_DOCUMENT_COMPLET PBDOM_Element pbdomelem PBDOM_Element pbdomelements[] Long ll_row pbdombuilder = create PBDOM_BUILDER try i_PBDOM_DOCUMENT_COMPLET = pbdombuilder.buildfromfile("invoice.xml") //la ligne qui suit est remplacée par plusieurs pour aider le debuggage //i_PBDOM_DOCUMENT_COMPLET.GetRootElement().GetChildElement("Invoice").GetChildElement("Module").GetChildElement ("InvoiceLine").GetContent(pbdom_obj_array) //Attention, je ne teste jamais si pbdomelem est trouvé (not null)... ;) pbdomelem = i_PBDOM_DOCUMENT_COMPLET.GetRootElement() //(dans mon fichier Invoice est le root) pbdomelem = pbdomelem.GetChildElement("Invoice") pbdomelem = pbdomelem.GetChildElement("Module") pbdomelem = pbdomelem.GetChildElement ("InvoiceLine") pbdomelem.GetChildElements("Harware", pbdomelements[]) for ll_row = 1 to UpperBound(pbdomelements[]) if not pbdomelements[ll_row].HasChildren() and not pbdomelements[ll_row].HasAttributes() then pbdomelem.RemoveContent(pbdomelements[ll_row]) end if next i_PBDOM_DOCUMENT_COMPLET.SaveDocument("filtered.xml") Catch (pbdom_exception ex1) MessageBox("Erreur", " !!! Erreur sur la suppression de balise Harware (af_suppression_balise) " + ex1.getMessage() ) return -1 end try destroy pbdombuilder return 0
avec un fichier des test
<Invoice> <Module> <InvoiceLine> <InvoiceLineNumber/> <LineCode>GROUPEMENT 1</LineCode> <FullLineDescription/> <Quantity>0</Quantity> <UnitPrice>0</UnitPrice> <LineValue>9983.11</LineValue> <LineComment/> <LineTax> <TaxCode>04</TaxCode> <TaxRate>19.60</TaxRate> <TaxValue>1956.68</TaxValue> </LineTax> <LineValueWithTax>11939.79</LineValueWithTax> <DiscountRate>0</DiscountRate> <NetUnitPrice>0</NetUnitPrice> <SpecialTax/> <Serial> </Serial> <Harware/> <Harware/> <Harware someattrib=""/> <Harware/> <Harware>some content</Harware> <Harware/> </InvoiceLine> </Module> </Invoice>
j'obtiens le fichier suivant (étonnamment, les éléments supprimés semble laisser un espace dans le fichier, j'espère que cela ne te gène pas ?), ça semble fonctionner (testé sur du PB11.5) :
<Invoice> <Module> <InvoiceLine> <InvoiceLineNumber/> <LineCode>GROUPEMENT 1</LineCode> <FullLineDescription/> <Quantity>0</Quantity> <UnitPrice>0</UnitPrice> <LineValue>9983.11</LineValue> <LineComment/> <LineTax> <TaxCode>04</TaxCode> <TaxRate>19.60</TaxRate> <TaxValue>1956.68</TaxValue> </LineTax> <LineValueWithTax>11939.79</LineValueWithTax> <DiscountRate>0</DiscountRate> <NetUnitPrice>0</NetUnitPrice> <SpecialTax/> <Serial> </Serial> <Harware someattrib=""/> <Harware>some content</Harware> </InvoiceLine> </Module> </Invoice>
Hors ligne
Bonjour,
Un grand merci, cela fonctionne à merveille, et en plus j'ai compris mon erreur de parsing, on avance, doucement mais surement,
Hors ligne
wazou1812 a écrit:
Code: pb
//... For ll_row = 1 to upperbound(pbdom_obj_array[]) If i_PBDOM_DOCUMENT_COMPLET.GetRootElement().GetChildElement("Invoice").GetChildElement("Module").GetChildElement ("InvoiceLine").GetChildElement ("Harware").HasChildren() = false then i_PBDOM_DOCUMENT_COMPLET.GetRootElement().GetChildElement("Invoice").GetChildElement("Module").GetChildElement ("InvoiceLine").RemoveChildElement("Harware") End if NEXT
J'ai oublié de préciser un point : je ne connais pas la longueur et la complexité des documents qui sont traités par ton code, mais de manière générale, il vaudrait mieux
- stocker une fois l'élément pour lequel on veut supprimer des sous-éléments dans une variable
- réutiliser cette variable pour le if et pour le Remove()
Plutôt que se retaper 1 ou 2x GetRoot().get().get().get().get()... à chaque tour de boucle. Ça doit finir par faire une différence de perfs visible au bout de quelques itérations, sachant que PBDOM est une extension PBNI et qu'on saute entre PB et l'extension à chaque appel et chaque retour de méthode... Enfin c'est juste mon avis
Hors ligne
Merci Seki pour ces précisions.
J'étais effectivement repartie de ton code pour finaliser le mien , en mettant dans la variable uniquement la partie de l'arbre qui m'interesse.
En l’occurrence, il s'agit de factures client, avec une facture par fichier XML,
Encore merci pour ces précieux conseils,
Hors ligne
Bonjour,
Encore une petite manipulation des fichiers pbdom que je n'arrive pas à faire.
une partie de mon fichier est ainsi
<MailingAddressBuyer> <CompanyName/> <BillingManager/> <Address1/> <Address2/> <Address3/> <City/> <Postcode/> <Country/> </MailingAddressBuyer>
Avec l'ensemble du contenu vide.
Le résultat attendu voudrait que dans ce cas, l'ensemble de la balise <MailingAddressBuyer> n'apparaisse pas dans le fichier xml final.
Fonctionnellement, si l'élément <CompanyName/> est vide, nous pouvons considérer que la balise <MailingAddressBuyer> est à supprimer.
J'ai eu beau retourner le pb dans tous les sens, pas moyen d'arriver au résultat attendu.
Auriez-vous une petite idée ?
Merci d'avance,
Hors ligne
Bonjour,
Pour vous aider dans votre recherche, voici un extrait complet du fichier xml, l'objectif étant de supprimer l'élément MailingAddressBuyer dans son ensemble , si au moins le 1er element est vide.
Merci d'avance pour votre aide,
<?xml version="1.0" encoding="UTF-16LE" standalone="yes"?> <Invoice> <DocumentNumber>60809</DocumentNumber> <DocumentLanguage>FR</DocumentLanguage> <VATExemption>N</VATExemption> <Supplier> <phoneNumber>+33 1 69 00 00 00</phoneNumber> <FaxNumber>+33 1 69 00 00 00</FaxNumber> <Web>www.TOTO.fr</Web> <Capital>9999.00</Capital> <LegalForm>SAS</LegalForm> <Agency/> <AddressSupplier> <Address1>1, Rue de Terre Neuve</Address1> <Address2>Les Ulis . CS60062</Address2> <Address3/> <City>Courtaboeuf cedex</City> <Postcode>91978</Postcode> <Country>France</Country> </AddressSupplier> <ContactSupplier> <ContactId/> <ContactName>HENNEQUIN DENIS</ContactName> <ContactPhone>0033 169182032</ContactPhone> </ContactSupplier> </Supplier> <Buyer> <VATRegistrationId>55555</VATRegistrationId> <Siret>55555</Siret> <Name>TEST</Name> <AddressBuyer> <Address1>SERVICE FACTURIER</Address1> <Address2>13 Pl VENDOME</Address2> <Address3>GA JUST 2</Address3> <City>PARIS CDX 1</City> <Postcode>75042</Postcode> <Country>France</Country> </AddressBuyer> <MailingAddressBuyer> <Address1/> <Address2/> <Address3/> <City/> <Postcode/> <Country/> </MailingAddressBuyer> <ECSReference>900152</ECSReference> </Buyer> </Invoice>
Hors ligne
Salut,
tu peux utiliser GetElementsByTagName('MailingAddressBuyer'), puis sur chaque noeud MailingAddressBuyer
regarder le texte de l'enfant 'Address1', si il est vide alors appel Detach sur le noeaud MailingAddressBuyer.
Voici un exemple à remanier :-p
>pbperl115 +pbdom115.pbd -MPowerbuilder=:all trimtag.pl
#trimtag.pl $builder = Create(pbdom_builder); $doc = $builder->BuildFromFile('sample.xml'); $doc->GetElementsByTagName('MailingAddressBuyer', \@elts ); $_->Detach foreach grep{ my $child=$_->GetChildElement('Address1'); defined $child and $child->GetText eq '' } @elts; print $doc->SaveDocumentIntoString;
ce qui donne :
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <Invoice> <DocumentNumber>60809</DocumentNumber> <DocumentLanguage>FR</DocumentLanguage> <VATExemption>N</VATExemption> <Supplier> <phoneNumber>+33 1 69 00 00 00</phoneNumber> <FaxNumber>+33 1 69 00 00 00</FaxNumber> <Web>www.TOTO.fr</Web> <Capital>9999.00</Capital> <LegalForm>SAS</LegalForm> <Agency/> <AddressSupplier> <Address1>1, Rue de Terre Neuve</Address1> <Address2>Les Ulis . CS60062</Address2> <Address3/> <City>Courtaboeuf cedex</City> <Postcode>91978</Postcode> <Country>France</Country> </AddressSupplier> <ContactSupplier> <ContactId/> <ContactName>HENNEQUIN DENIS</ContactName> <ContactPhone>0033 169182032</ContactPhone> </ContactSupplier> </Supplier> <Buyer> <VATRegistrationId>55555</VATRegistrationId> <Siret>55555</Siret> <Name>TEST</Name> <AddressBuyer> <Address1>SERVICE FACTURIER</Address1> <Address2>13 Pl VENDOME</Address2> <Address3>GA JUST 2</Address3> <City>PARIS CDX 1</City> <Postcode>75042</Postcode> <Country>France</Country> </AddressBuyer> <ECSReference>900152</ECSReference> </Buyer> </Invoice>
Dernière modification par xlat (06-07-2012 13:30:48)
Hors ligne
xlat a écrit:
Code: pbperl
#trimtag.pl [...]
Prosélytisme !
Hors ligne
xlat a écrit:
Salut,
tu peux utiliser GetElementsByTagName('MailingAddressBuyer'), puis sur chaque noeud MailingAddressBuyer
regarder le texte de l'enfant 'Address1', si il est vide alors appel Detach sur le noeaud MailingAddressBuyer.
Voici un exemple à remanier :-p
>pbperl115 +pbdom115.pbd -MPowerbuilder=:all trimtag.plCode: pbperl
#trimtag.pl $builder = Create(pbdom_builder); $doc = $builder->BuildFromFile('sample.xml'); $doc->GetElementsByTagName('MailingAddressBuyer', \@elts ); $_->Detach foreach grep{ my $child=$_->GetChildElement('Address1'); defined $child and $child->GetText eq '' } @elts; print $doc->SaveDocumentIntoString;
ce qui donne :Code: xml
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <Invoice> <DocumentNumber>60809</DocumentNumber> <DocumentLanguage>FR</DocumentLanguage> <VATExemption>N</VATExemption> <Supplier> <phoneNumber>+33 1 69 00 00 00</phoneNumber> <FaxNumber>+33 1 69 00 00 00</FaxNumber> <Web>www.TOTO.fr</Web> <Capital>9999.00</Capital> <LegalForm>SAS</LegalForm> <Agency/> <AddressSupplier> <Address1>1, Rue de Terre Neuve</Address1> <Address2>Les Ulis . CS60062</Address2> <Address3/> <City>Courtaboeuf cedex</City> <Postcode>91978</Postcode> <Country>France</Country> </AddressSupplier> <ContactSupplier> <ContactId/> <ContactName>HENNEQUIN DENIS</ContactName> <ContactPhone>0033 169182032</ContactPhone> </ContactSupplier> </Supplier> <Buyer> <VATRegistrationId>55555</VATRegistrationId> <Siret>55555</Siret> <Name>TEST</Name> <AddressBuyer> <Address1>SERVICE FACTURIER</Address1> <Address2>13 Pl VENDOME</Address2> <Address3>GA JUST 2</Address3> <City>PARIS CDX 1</City> <Postcode>75042</Postcode> <Country>France</Country> </AddressBuyer> <ECSReference>900152</ECSReference> </Buyer> </Invoice>
Bonjour,
Tout d'abord, merci pour ton retour.
Désolée pour la réponse un peu tardive, mais congés + autres priorités ont retardé ma réponse.
Et effectivement, j'avais zappé la fonctionnalité 'detach' qui effectivement fonctionne très bien dans ce cas.
Encore merci, sujet RESOLU,
Hors ligne