Pourquoi la fonction PROC FCMP renvoie-t-elle toujours 33 octets et pas plus?

StackOverflow https://stackoverflow.com/questions/1032238

  •  06-07-2019
  •  | 
  •  

Question

J'ai la fonction suivante définie via PROC FCMP. Le code devrait être assez évident et relativement simple. Je retourne la valeur d'un attribut d'une ligne de XHTML. Voici le code:

proc fcmp outlib=library.funcs.crawl;
    function getAttr(htmline $, Attribute $) $;

       /*-- Find the position of the match --*/
    Pos = index( htmline , strip( Attribute )||"=" );

       /*-- Now do something about it --*/
       if pos > 0 then do;
          Value = scan( substr( htmline, Pos + length( Attribute ) + 2), 1, '"');
       end;
       else Value = "";
       return( Value);
    endsub;
run;

Quoi que je fasse avec l'instruction length ou attrib pour essayer de déclarer explicitement le type de données renvoyé, elle ne renvoie TOUJOURS qu'un maximum de 33 octets de la chaîne demandée, quelle que soit la longueur de la valeur de retour réelle. Cela se produit quel que soit l'attribut que je recherche. Le même code (codé en dur) dans une étape de données renvoie les résultats corrects et est donc lié à PROC FCMP.

Voici le datastep que j'utilise pour le tester (où PageSource.html est un fichier HTML contenant des attributs conformes à xhtml et qui est entièrement entre guillemets):

data TEST;
length href $200;
infile "F:\PageSource.html";

input;

htmline = _INFILE_;

href = getAttr( htmline, "href");
x = length(href);

run;

UPDATE: cela semble fonctionner correctement après la mise à niveau vers SAS9.2 - Version 2

Était-ce utile?

La solution 3

J'ai fini par reculer en utilisant les fonctions de pas de données définies par FCMP. Je ne pense pas qu'ils soient prêts pour le prime time. Non seulement je ne pouvais pas résoudre le problème du retour sur 33 octets, mais cela provoquait régulièrement un crash de SAS.

Revenons donc à la bonne vieille technologie (vieille de plusieurs décennies) des macros. Cela fonctionne:

/*********************************/
/*= Macro to extract Attribute  =*/
/*= from XHTML string           =*/
/*********************************/
%macro getAttr( htmline, Attribute, NewVar );
   if index( &htmline , strip( &Attribute )||"=" ) > 0 then do;
      &NewVar = scan( substr( &htmline, index( &htmline , strip( &Attribute )||"=" ) + length( &Attribute ) + 2), 1, '"' );
   end;
%mend;

Autres conseils

Dans ce cas, une commande de pointeur d'entrée devrait suffire. espérons que cela aide.

/* create a test input file */
data _null_;
  file "f:\pageSource.html";
  input;
  put _infile_;
cards4;
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="w3.org/StyleSheets/TR/W3C-REC.css"; type="text/css"?>
;;;;
run;

/* extract the href attribute value, if any.                          */
/* assuming that the value and the attribute name occurs in one line. */
/* and max length is 200 chars.                                       */
data one;
  infile "f:\pageSource.html" missover;
  input @("href=") href :$200.;
  href = scan(href, 1, '"'); /* unquote */
run;

/* check */
proc print data=one;
run;
/* on lst
Obs                  href
 1
 2     w3.org/StyleSheets/TR/W3C-REC.css
*/

Je pense que le problème (bien que je ne sache pas pourquoi) se situe dans la fonction d'analyse - il semble tronquer l'entrée de substr (). Si vous extrayez la fonction substr de scan (), assignez le résultat de cette fonction à une nouvelle variable que vous transmettez ensuite à scan, cela semble fonctionner.

Voici ce que j'ai couru:

proc fcmp outlib=work.funcs.crawl;
    function getAttr(htmline $, Attribute $) $;
    length y $200;
       /*-- Find the position of the match --*/
    Pos = index( htmline , strip( Attribute )||"=" );

       /*-- Now do something about it --*/
       if pos > 0 then do;
          y=substr( htmline, Pos + length( Attribute ) + 2);
          Value = scan( y, 1, '"');       
       end;
       else Value = "";
       return( Value);
    endsub;
run;

options cmplib=work.funcs;

data TEST;
length href $200;
infile "PageSource.html";

input;

htmline = _INFILE_;
href = getAttr( htmline, "href");
x = length(href);
run;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top