Subject: [xsl] I love programs that output programs From: "Roger L Costello costello@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Fri, 17 Jan 2025 20:21:58 -0000 |
Hi Folks, Recently I was reading Brian Kernighan's new book on AWK, and it showed a wicked cool AWK program that outputs an AWK program. Below is the AWK program, followed by the equivalent XSLT program. The task is to run some checks on a password file. Here is a sample password file: root:qyxRi2uVjrg:0:2::/: jd:1L./v6iblzzNE:9:1:John Doe:/usr/jd: jt:otxs1oToyvMQ:15:1:Jim Thomson:/usr/jt: uucp:xutIBs2hKtcls:48:1:uucp daemon:/usr/lib/uucp:uucico sm:xNqy//GDc8FFg:170:2:Sally Smith:/usr/sm: a!f:aiopaIAjfaI:21:1:Fake Person:/usr/a!f: jv::1:Jules Verne:/usr/jv: ah:dsjkdAJ:34:1:Alexander Hamilton Fields within each line are delimited by a colon. The first field is the username. It should be alphanumeric. Check each line to confirm that its username is alphanumeric. The second field is an encrypted version of the password. The field should not be empty. Check each line to confirm that it's not empty. I won't discuss the other fields. The third check confirms that each line has 7 fields. ----------------------------------------------------------------------------- --------------- AWK Version ----------------------------------------------------------------------------- --------------- Here's an AWK expression to check whether a line does not have 7 fields: NF != 7 [NF = Number of Fields, NF is a built-in function] Here's an AWK expression to check whether the second field is empty: $2 == "" [$1 denotes the first field, $2 denotes the second field, etc.] Here's an AWK expression to check whether the first field is not alphanumeric: $1 ~ /[^A-Za-z0-9]/ [tilda means "matches"; the stuff between slashes is a regex] Put the expressions into a file, along with a description: NF != 7 does not have 7 fields $2 == "" no password $1 ~ /[^A-Za-z0-9]/ nonalphanumeric user id The following AWK program inputs those expressions and outputs a program that applies the expressions to each line of the password file: BEGIN { FS = "\t+" } { printf("%s {\n\tprintf(\"line %%d, %s: %%s\\n\",NR,$0) }\n", $1, $2) } [FS = Field Separator. NR = Row Number, $0 denotes the entire line. If you know the C printf statement you can probably figure out what that printf is doing--it is outputting a printf] Run the AWK program; it generates this AWK program: NF != 7 { printf("line %d, does not have 7 fields: %s\n",NR,$0) } $2 == "" { printf("line %d, no password: %s\n",NR,$0) } $1 ~ /[^A-Za-z0-9]/ { printf("line %d, nonalphanumeric user id: %s\n",NR,$0) } Now run that generated AWK program against the password file. It reveals errors in the password file: line 6, nonalphanumeric user id: a!f:aiopaIAjfaI:21:1:Fake Person:/usr/a!f: line 7, does not have 7 fields: jv::1:Jules Verne:/usr/jv: line 7, no password: jv::1:Jules Verne:/usr/jv: line 8, does not have 7 fields: ah:dsjkdAJ:34:1:Alexander Hamilton ----------------------------------------------------------------------------- --------------- XSLT/XPath Version ----------------------------------------------------------------------------- --------------- Format the password file as XML: <passwds> <passwd>root:qyxRi2uVjrg:0:2::/:</passwd> <passwd>jd:1L./v6iblzzNE:9:1:John Doe:/usr/jd:</passwd> <passwd>jt:otxs1oToyvMQ:15:1:Jim Thomson:/usr/jt:</passwd> <passwd>uucp:xutIBs2hKtcls:48:1:uucp daemon:/usr/lib/uucp:uucico</passwd> <passwd>sm:xNqy//GDc8FFg:170:2:Sally Smith:/usr/sm:</passwd> <passwd>a!f:aiopaIAjfaI:21:1:Fake Person:/usr/a!f:</passwd> <passwd>jv::1:Jules Verne:/usr/jv:</passwd> <passwd>ah:dsjkdAJ:34:1:Alexander Hamilton</passwd> </passwds> Create XPath expressions for the three checks and put the XPath expressions into a file: <validation_tests> <test> <xpath>count(tokenize(.,':')) ne 7</xpath> <message>does not have 7 fields</message> </test> <test> <xpath>tokenize(.,':')[2] eq ''</xpath> <message>no password</message> </test> <test> <xpath>string-length(translate(tokenize(., ':')[1], 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', '')) ne 0</xpath> <message>nonalphanumeric user id</message> </test> </validation_tests> This XSLT program inputs the XPath expressions file and outputs an XSLT program that applies the XPath expressions: <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:axsl="http://www.w3.org/1999/XSL/Transform/alias" version="3.0"> <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/> <xsl:template match="/"> <axsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"> <axsl:template match="/"> <axsl:for-each select="/passwds/passwd"> <axsl:variable name="passwd" select="."/> <xsl:for-each select="/validation_tests/test"> <axsl:choose> <axsl:when test="{xpath}"> <axsl:message>line <axsl:value-of select="position()"/>, <xsl:value-of select="message"/>: <axsl:value-of select="$passwd"/></axsl:message> </axsl:when> </axsl:choose> </xsl:for-each> </axsl:for-each> </axsl:template> </axsl:stylesheet> </xsl:template> </xsl:stylesheet> Here is the XSLT it generates: <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"> <xsl:template match="/"> <xsl:for-each select="/passwds/passwd"> <xsl:variable name="passwd" select="."/> <xsl:choose> <xsl:when test="count(tokenize(., ':')) ne 7"> <xsl:message>line <xsl:value-of select="position()"/>, does not have 7 fields: <xsl:value-of select="$passwd"/></xsl:message> </xsl:when> </xsl:choose> <xsl:choose> <xsl:when test="tokenize(., ':')[2] eq ''"> <xsl:message>line <xsl:value-of select="position()"/>, no password: <xsl:value-of select="$passwd"/></xsl:message> </xsl:when> </xsl:choose> <xsl:choose> <xsl:when test="string-length(translate(tokenize(., ':')[1], 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', '')) ne 0"> <xsl:message>line <xsl:value-of select="position()"/>, nonalphanumeric user id: <xsl:value-of select="$passwd"/></xsl:message> </xsl:when> </xsl:choose> </xsl:for-each> </xsl:template> </xsl:stylesheet> Run the generated XSLT program against the password file; these messages are displayed: line 6, nonalphanumeric user id: a!f:aiopaIAjfaI:21:1:Fake Person:/usr/a!f: line 7, does not have 7 fields: jv::1:Jules Verne:/usr/jv: line 7, no password: jv::1:Jules Verne:/usr/jv: line 8, does not have 7 fields: ah:dsjkdAJ:34:1:Alexander Hamilton
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Announcing Balisage 2025 - Ma, B Tommie Usdin btusd | Thread | Re: [xsl] I love programs that outp, Martin Honnen martin |
Re: [xsl] Get the duplicates in a l, Philip Fearon pgfear | Date | Re: [xsl] I love programs that outp, Martin Honnen martin |
Month |