Domanda

Ho la seguente funzione definita tramite PROC FCMP. Il punto del codice dovrebbe essere piuttosto ovvio e relativamente semplice. Sto restituendo il valore di un attributo da una riga di XHTML. Ecco il codice:

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;

Indipendentemente da ciò che faccio con la lunghezza o l'istruzione attrib per provare a dichiarare esplicitamente il tipo di dati restituito, restituisce SEMPRE solo un massimo di 33 byte della stringa richiesta, indipendentemente dalla durata del valore restituito effettivo. Ciò accade indipendentemente dall'attributo che sto cercando. Lo stesso codice (hardcoded) in un passaggio di dati restituisce i risultati corretti, quindi è correlato a PROC FCMP.

Ecco il datastep che sto usando per testarlo (dove PageSource.html è qualsiasi file html che ha attributi conformi xhtml - completamente citato):

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

input;

htmline = _INFILE_;

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

run;

AGGIORNAMENTO: sembra funzionare correttamente dopo l'aggiornamento a SAS9.2 - Versione 2

È stato utile?

Soluzione 3

Ho finito per tornare indietro usando le funzioni di step di dati definiti da FCMP. Non penso che siano pronti per la prima serata. Non solo non ho potuto risolvere il problema di restituzione a 33 byte, ma ha iniziato regolarmente a bloccare SAS.

Quindi torniamo alla buona vecchia (decennale) tecnologia delle macro. Questo funziona:

/*********************************/
/*= 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;

Altri suggerimenti

In questo caso, un controllo puntatore di input dovrebbe essere sufficiente. spero che questo aiuti.

/* 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
*/

Penso che il problema (anche se non so perché) sia nella funzione scan - sembra troncare l'input da substr (). Se estrai la funzione substr da scan (), assegna il risultato della funzione substr a una nuova variabile che poi passi alla scansione, sembra funzionare.

Ecco cosa ho eseguito:

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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top