IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

APIs XML Discussion :

Problème Buffer XSLTCOmpiledTransform


Sujet :

APIs XML

  1. #1
    Membre expérimenté
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Avril 2008
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 875
    Points : 1 394
    Points
    1 394
    Par défaut Problème Buffer XSLTCOmpiledTransform
    Bonjour,
    Je travaille actuellement sur un projet XML->OpenXML (transformation en fichier word) pour la génération d'un catalogue produit à partir d'une base de données.

    Les API dont je me sers sont SAXON (pour les tests) et MSXML.NET pour la production.

    Tout a très bien fonctionné jusqu'à aujourd'hui. Le volume du catalogue augmentant, je rencontre un nouveau problème. MSXML interrompt brutalement la transformation sans générer d'exception, et le résultat est un XML mal formé (et en fait incomplet). SAXON lui se comporte très bien et continue de me générer le catalogue.

    En fouillant sur le net j'ai découvert que MSXML place la sortie de la transformation dans un buffer en mémoire. Dans le cas de mon code ci-dessous c'est dans un stream qui lui-même pointe vers une part du fichier word (la part document.xml).

    Il me semble que les modif ne sont écrites sur le disque que lors de l'appel de $streamR.flush().

    Comment faire pour qu'il écrive les modif sur le dique au fur eet à mesure de la transformation (en fait comment faire pour que mon stream n'utilise pas de buffer)

    PS: je poste dans le forum XML alors que je code en PowerShell avec API .NET mais je me dis que peut être quelqu'un sur ce forum a déjà rencontré ce problème

    PPS: à ceux qui vont me proposer d'utiliser saxon dans ma solution de prod, je ne peux pas le faire car saxon en utilisation professionnelle est sous licence

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
     
     #création d'une transformation
      [System.XML.XSL.XSLCompiledTransform]$transform=new-object -TypeName System.XML.XSL.XSLCompiledTransform
        #chargement du fichier de transformation
      $transform.Load($objtransformxsl.fullname)
     
      [system.reflection.assembly]::loadwithpartialname("WindowsBase")
      #obtention d'un pointeur de type package vers le fichier Word modele
      [system.IO.Packaging.Package]$pack=[System.IO.Packaging.Package]::open("$catalogue",[System.IO.Filemode]::Open,[System.IO.FileAccess]::ReadWrite)
     
      #on obtient un pointeur vers le flux de la part /word/document.xml
      [System.IO.Stream]$streamR=$pack.GetPart("/word/document.xml").GetStream([System.IO.FileMode]::Open,[System.IO.FileAccess]::ReadWrite)
      $streamR.setlength(0)
     
     
      #ajout de paramètres à la transformation
      [system.xml.xsl.xsltargumentlist]$xslargs= new-object -TypeName system.xml.xsl.XsltArgumentList
      $xslargs.addparam("avec_prix","",$avec_prix) 
     
     
      $transform.Transform("$formations",$xslargs,$streamR)
     
      $streamR.flush()
      $pack.flush()
      $pack.close() 
      #fermeture des flux
      $streamR.close()

  2. #2
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    Comment faire pour qu'il écrive les modif sur le dique au fur eet à mesure de la transformation (en fait comment faire pour que mon stream n'utilise pas de buffer)
    Vous pouvez essayer utilisant comme "output" un XmlWriter dirigeant vers un fichier.
    http://msdn.microsoft.com/en-us/library/ms163436.aspx
    Il se peut créer avec sa méthode statique Create().
    http://msdn.microsoft.com/en-us/library/ms162618.aspx
    Et vous le mettez à la place de $streamR.

  3. #3
    Membre expérimenté
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Avril 2008
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 875
    Points : 1 394
    Points
    1 394
    Par défaut
    Merci de m'aider. Malheureusement ça n'a pas changé le problème. par contre la transformation est plus performante.
    Je pense qu'il faut que j'implémente une boucle de lecture du flux transformé par tranche et écriture par tranche dans le flux de la part. J'ai du mal à trouver un code clair sur le net là dessus.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
     
     $objcatalogue=get-item $catalogue
      $objtransformxsl=get-item $transformxsl
      $objmodele=get-item $modele
      $objformations= get-item $formations
     
      #copie du plan modele
      trap{remove-item $catalogue}
      copy-item $modele $catalogue
     
      #création d'une transformation
      [System.XML.XSL.XSLCompiledTransform]$transform=new-object -TypeName System.XML.XSL.XSLCompiledTransform
     
      #chargement du fichier de transformation
      $transform.Load($objtransformxsl.fullname)
     
      [system.reflection.assembly]::loadwithpartialname("WindowsBase")
      #obtention d'un pointeur de type package vers le fichier Word modele
      [system.IO.Packaging.Package]$pack=[System.IO.Packaging.Package]::open("$catalogue",[System.IO.Filemode]::Open,[System.IO.FileAccess]::ReadWrite)
     
      #on obtient un pointeur vers le flux de la part /word/document.xml
      [System.IO.Stream]$streamR=$pack.GetPart("/word/document.xml").GetStream([System.IO.FileMode]::Open,[System.IO.FileAccess]::ReadWrite)
     
     
      $streamR.setlength(0)
      $streamR.flush()
     
      #création d'un xml writer
      [System.Xml.XmlWriter]$xmlwriter=[System.Xml.XmlWriter]::Create($streamR)
     
      #ajout de paramètres à la transformation
      [system.xml.xsl.xsltargumentlist]$xslargs= new-object -TypeName system.xml.xsl.XsltArgumentList
      $xslargs.addparam("avec_prix","",$avec_prix) 
     
      $transform.Transform("$formations",$xslargs,$xmlwriter)
      $xmlwriter.flushasync()
     
     
      $pack.flush()
      $pack.close() 
      #fermeture des flux
      $streamR.close()

  4. #4
    Membre expérimenté
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Avril 2008
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 875
    Points : 1 394
    Points
    1 394
    Par défaut
    bon après des recherches, il apparaît que la péthode transform fonctionne parfaitement. Elle produit systématiquement le fichier xml voulu, qu'il soit envoyé au préalable dans un flux ou dans un fichier.

    Le problème survient lorsque je fais la jonction avec avec le flux de la part. C'est lui qui tronque les données. Mais pourquoi?

  5. #5
    Membre expérimenté
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Avril 2008
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 875
    Points : 1 394
    Points
    1 394
    Par défaut
    Bon j'ai trouvé ma boucle chez ms dans un exemple de code .net que j'ai adapté au powershell. L'exemple conçoit une fonction spécifique copystream pour cet usage (alors que certaines classes stream proposent une ùméthode équivalente......)

    voilà le code de la fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    function cree-catalogue{param([string]$catalogue, [string]$modele, [string]$transformXSL, [string]$formations, [string]$avec_prix="false")
     
      $objcatalogue=get-item $catalogue
      $objtransformxsl=get-item $transformxsl
      $objmodele=get-item $modele
      $objformations= get-item $formations
     
      #copie du plan modele
      trap{remove-item $catalogue}
      copy-item $modele $catalogue
     
      #création d'une transformation
      [System.XML.XSL.XSLCompiledTransform]$transform=new-object -TypeName System.XML.XSL.XSLCompiledTransform
     
      #chargement du fichier de transformation
      $transform.Load($objtransformxsl.fullname)
     
     
      [system.reflection.assembly]::loadwithpartialname("WindowsBase")
      #obtention d'un pointeur de type package vers le fichier Word modele
      [system.IO.Packaging.Package]$pack=[System.IO.Packaging.Package]::open("$catalogue",[System.IO.Filemode]::Open,[System.IO.FileAccess]::ReadWrite)
     
      #on obtient un pointeur vers le flux de la part /word/document.xml
         [System.IO.Stream]$streamR=$pack.GetPart("/word/document.xml").GetStream([System.IO.FileMode]::Open,[System.IO.FileAccess]::ReadWrite)
     
      $streamR.setlength(0)
      $streamR.flush()
     
      #création d'un xml writer
      [System.Xml.XmlWriter]$xmlwriter=[System.Xml.XmlWriter]::Create("c:\temp.xml")
     
      #ajout de paramètres à la transformation
      [system.xml.xsl.xsltargumentlist]$xslargs= new-object -TypeName system.xml.xsl.XsltArgumentList
      $xslargs.addparam("avec_prix","",$avec_prix) 
     
        $transform.Transform("$formations",$xslargs,$xmlwriter)
      $xmlwriter.flush()
      $xmlwriter.Close()
       [system.IO.filestream]$streamfile=New-Object -TypeName System.IO.FileStream -ArgumentList "c:\temp.xml","Open"
     
    			$bufSize= 1024
    			[Byte[]]$buf=[byte[]](,0x00 * $bufSize)
    			#$bytesRead= 1
    			$bytesRead = $streamfile.Read($buf, 0, $bufSize)
    "test1"
    $bytesRead
    $buf
    			While($bytesRead -gt 0){
    				$streamR.Write($buf, 0, $bytesRead)
    				$bytesRead = $streamfile.Read($buf, 0, $bufSize)
                    $streamR.flush()
    "test2"
    $bytesRead
                }
     
     
     
       $streamR.flush()
      #on obtient un pointeur vers le flux de du fichier XML transformé
      $pack.flush()
      $pack.close() 
      #fermeture des flux
      $streamR.close()
     
    }
    donc ça marche, je peux de nouveau générer de gros documents, mais au prix d'une performance médiocre. Mes appels à flush à chaque tour de boucle sont catastrophiques, mais sinon cela ne marche pas.

    Est ce que quelqu'un a une autre idée

    PS: pour les modos, il me semble que mon problème est devenu un pur problème . NET. Est il possible de déplacer cette discussion?

Discussions similaires

  1. Problème de buffer avec des int et des char
    Par Lolita59 dans le forum Réseau
    Réponses: 23
    Dernier message: 04/05/2006, 11h09
  2. SQL + problème de buffer-oracle version 8.1.7
    Par new_wave dans le forum Oracle
    Réponses: 4
    Dernier message: 21/11/2005, 14h51
  3. Problème de Z-Buffer
    Par Dmnbp7ip dans le forum DirectX
    Réponses: 1
    Dernier message: 06/04/2005, 01h26
  4. Problème de Stencil-buffer
    Par Steki-kun dans le forum OpenGL
    Réponses: 2
    Dernier message: 18/03/2005, 23h42
  5. [fread] Problème de lecture de buffer
    Par karl3i dans le forum C
    Réponses: 2
    Dernier message: 25/09/2003, 09h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo