Frage

Ich habe die folgende Funktion über PROC FCMP definiert. Der Punkt des Codes sollte ziemlich offensichtlich und relativ unkompliziert sein. Ich bin die Rückgabe des Werts eines Attributs aus einer Reihe von XHTML. Hier ist der 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;

Egal, was ich mit der Länge oder attrib Anweisung tun, um zu versuchen explizit der Datentyp zurückgegeben zu erklären, es gibt immer nur ein Maximum von 33 Bytes des angeforderten Zeichenfolge, unabhängig davon, wie lange der tatsächliche Rückgabewert ist. Dies geschieht unabhängig davon, welches Attribut Ich suche. Der gleiche Code (hart codiert) in einem Datenschritt liefert die richtigen Ergebnisse so, dies zu PROC FCMP verwandt ist.

Hier ist die datastep Ich verwende es zu testen (wo PageSource.html jede HTML-Datei, die XHTML-konform Attribute hat - vollständig zitiert):

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

input;

htmline = _INFILE_;

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

run;

UPDATE: Dies scheint nach dem Upgrade auf SAS9.2 richtig funktioniert - Release 2

War es hilfreich?

Lösung 3

beenden ich aus mit FCMP definierten Daten Schritt Funktionen sichern. Ich glaube nicht, dass sie für Hauptsendezeit bereit sind. Nicht nur konnte ich die 33-Byte-Rückkehr Problem nicht lösen, aber es begann SAS regelmäßig abstürzt.

Also zurück zum guten alten (Jahrzehnte alt) Technologie von Makros. Dies funktioniert:

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

Andere Tipps

In diesem Fall wird eine Eingangszeigersteuerung sollte ausreicht. hoffe, das hilft.

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

Ich denke, das Problem (obwohl ich weiß nicht, warum) in der Scan-Funktion - es Eingang zu sein scheint von substr Kürzen (). Wenn Sie die Funktion substr aus Scan () ziehen, um das Ergebnis der Funktion substr einen neue Variablen zuweisen, das Sie dann scannen passieren, scheint es zu funktionieren.

Hier ist, was ich lief:

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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top