Subject: Re: [xsl] I love programs that output programs From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Fri, 17 Jan 2025 21:41:21 -0000 |
Another note: People may want to generate not xslt-code, but pure XPath code (and evaluate it with xsl:evaluate in XSLT, or using fn:load-xquery module, if they don't have an xslt-capable host. https://qt4cg.org/specifications/xpath-functions-40/Overview.html#func-load-x query-module On Fri, Jan 17, 2025 at 1:36b/PM Dimitre Novatchev <dnovatchev@xxxxxxxxx> wrote: > Hi Roger, > > > <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> > > This seems rather unreadable to me, and I would definitely want to avoid > having to debug two different transformations - too-inconvenient. > > What I would do instead: > > 1. Generate the new XSLT code as a string. This is more readable, > because no <xsl:namespace-alias> directive is needed and we will be using > just/only the wellknown "xsl:" prefix. > 2. Call the standard XPath fn:transform, passing to it as a parameter > the generated string. > https://www.w3.org/TR/xpath-functions-31/#func-transform > 3. This can be combined with the "fill-in the blanks" approach, where > the skeleton for the generated code is contained in an external file, and > only its (marked as) variable parts are dynamically replaced with > calculated values. > > Also, this approach has the advantage that the xslt code generation can be > coded not only in XSLT, but even in pure XPath 3. > > As they say, "just my 2c." :) > > Thanks, > Dimitre > > > > On Fri, Jan 17, 2025 at 12:22b/PM Roger L Costello costello@xxxxxxxxx < > xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > >> 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 >> >> >> > > > -- Cheers, Dimitre Novatchev --------------------------------------- Truly great madness cannot be achieved without significant intelligence. --------------------------------------- To invent, you need a good imagination and a pile of junk ------------------------------------- Never fight an inanimate object ------------------------------------- To avoid situations in which you might make mistakes may be the biggest mistake of all ------------------------------------ Quality means doing it right when no one is looking. ------------------------------------- You've achieved success in your field when you don't know whether what you're doing is work or play ------------------------------------- To achieve the impossible dream, try going to sleep. ------------------------------------- Facts do not cease to exist because they are ignored. ------------------------------------- Typing monkeys will write all Shakespeare's works in 200yrs.Will they write all patents, too? :) ------------------------------------- Sanity is madness put to good use. ------------------------------------- I finally figured out the only reason to be alive is to enjoy it.
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] I love programs that outp, Roger L Costello cos | Thread | Re: [xsl] I love programs that outp, Liam R. E. Quin liam |
Re: [xsl] I love programs that outp, Dimitre Novatchev dn | Date | [xsl] Running XSLT from Python, dvint@xxxxxxxxx |
Month |