- Drew
Regards,
Mike Sharp
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/ | node()">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:copy>
</xsl:copy>
</xsl:template>
<xsl:template match="Address">
<BuyerAddress>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()"/>
</BuyerAddress>
</xsl:template>
</xsl:stylesheet>
"Drew" <andre...@yahoo.com> wrote in message
news:e3fb65d3.03042...@posting.google.com...
btw, BizTalk Mapper tool might be helpful here. It allows to map
visually two XML schema (XDR only unfortunately) and generate XSLT
stylesheet to transform one to another.
--
Oleg Tkachenko
http://www.tkachenko.com/blog
Multiconn Technologies, Israel
Chris.
"Oleg Tkachenko" <ol...@multiconn.com> wrote in message news:uwWNdGBD...@TK2MSFTNGP12.phx.gbl...
Or to put it in another way, XSelerator is for the professional XSLT
programmer.
=====
Cheers,
Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
I love them both (apart from my Xselerator trial period is about to run out! - better get the credit card out then and
put my money where my mouth is I suppose :))
I tried XMLSpy but could never really feel comfortable with it for some reason - that'll be the personal preferences
again :)
Turbo has it's quirks cos it's Java written but the graphical representation of the XML to XML template matches is very
useful. Xselerator is a lot better for me cos it has all the intellisense for both XSLT and HTML (which for a starting
out novice like me is essential - you get to see options that you'd never remember from reading books).
Anyway - a newsgroup is not really a good place for my thoughts so I'll stop there.
BTW: Dimitre, I can't remember if you are associated with a specific XSLT development tool? If you are then I'd love to
trial it. Unlike my VB development life - where MS and Visual Basic 6.0 was the only tool available to me - I'm trying
to get my hands on as many XML and XSLT tools as possible so I can get a better handle on which suit me (for what I'm
doing - generally XML to XML and XML to HTML).
Regards,
Chris Barber.
"Dimitre Novatchev" <dnova...@yahoo.com> wrote in message news:b8ee9r$92els$1...@ID-152440.news.dfncis.de...
Chris,
I produced the XPath Visualizer for IE (3 years ago) and for Mozilla (6
months ago). People say it is a useful XPath learning tool. It is absolutely
free and can be obtained at:
http://www.topxml.com/xpathvisualizer/default.asp (for IE)
http://www.topxml.com/code/default.asp?p=3&id=v20021221025528&ms=30&l=&sw=All
(for Mozilla)
However, I consider as my personal achievement the implementation in XSLT of
a number of some of the most basic functional programming design patterns
(e.g. higher-order functions, partial application, folding (primitive
recursion) over node-sets and strings, etc.). This is what the FXSL
functional programming library for XSLT offer. The project page for FXSL
is:
https://sourceforge.net/projects/fxsl/
Some detailed materials explaining these basic FP design patterns and their
concrete implementation and use are contained on the FXSL home page:
I hope these fit at least partially what you're looking for.
I got hold of the FXSL download but I'm a bit stumped as to what I'm supposed to do with it? There appears to be a
library of XML and XSL documents but I can;t find any significant documentation on what or how they can be applied?
Thanks,
Chris.
"Dimitre Novatchev" <dnova...@yahoo.com> wrote in message news:b8eqvt$8phdl$1...@ID-152440.news.dfncis.de...
Just start reading the materials on http://fxsl.sf.net
Start with this one:
http://fxsl.sourceforge.net/articles/FuncProg/Functional%20Programming.html
You will find very detailed explanations and many examples.
Thanks.
Chris.
"Dimitre Novatchev" <dnova...@yahoo.com> wrote in message news:b8fqlj$98cck$1...@ID-152440.news.dfncis.de...
In a few simple words -- FXSL is a functional programming library for XSLT.
It can be a powerful tool for XSLT programming, which increases programmer
efficiency by providing support for much higher level of software
abstraction, encapsulation and re-use.
Problems that have traditionally been considered "difficult or impossible"
to solve with XSLT (e.g. text processing, complicated numerical methods,
combinatorial algorithms) are quite straightforward solved with XSLT.
>Just start reading the materials on http://fxsl.sf.net
>http://fxsl.sourceforge.net/articles/FuncProg/Functional%20Programming.html
>You will find very detailed explanations and many examples.
Unfortunately, the explanations are lacking. It's a language without
definition - the 'made-up' words of Lewis Carroll.
For ex:
The function sum that computes the sum of the elements of a list can
be defined as follows:
sum [] = 0
sum (n:ns) = n + sum ns
I'm guessing it would seem extremely tedious, and almost pointless, to
explain the notation and the ideas and wording behind it? CS101
somewhere, instead?
Or CS301 for ex:
http://undergraduate.cs.uwa.edu.au/courses/230.301/lectureNotes/22/23.pdf
No, it is said that this is how one would write it in *Haskell*. And there's
a link to the Haskell home page, a Haskell tutorial and a book on Haskell.
> I'm guessing it would seem extremely tedious, and almost pointless, to
> explain the notation and the ideas and wording behind it?
This is not a course in computer science. And part of the value is exactly
in the fact that not everything will be completely understood by everybody
on the first reading. Without a challenge this page would be of no value to
anyone.
This page has been accesed many thousands times and I'm glad now we have the
first remark that it is not completely understandable.
>This is not a course in computer science. And part of the value is exactly
>in the fact that not everything will be completely understood by everybody
>on the first reading. Without a challenge this page would be of no value to
>anyone.
>This page has been accesed many thousands times and I'm glad now we have the
>first remark that it is not completely understandable.
Glad I could be of service. It is a lot to read, those page 11 links.
But I'm sure it would answer the questions about the notation, etc.
I hope it isn't lost that xslt is not only useful, but pretty darned
easy to learn. I came across it less than a week ago. And I was able
to create a 'template', in that time, that probably did in a
relatively few lines - with long tags, admittedly - what I might still
be working on with vb, and recordsets and joins, filtering, sorting,
and so on. This xslt is, by design, literally template based. As a way
to transform a raw database into an html page, it's a wonder more
people aren't talking about this. As I wrote when I first found this
ng, it's pretty quiet compared to other ngs, or at least it is on the
servers I used to read the messages.
I would add, too, that without the xsl:script or msxsl:script feature,
it would be near impossible to get certain things done. It's sort of
the equivalent of plug-in filters for a graphics programs. I notice
the fxsl uses no xsl:script?
> I would add, too, that without the xsl:script or msxsl:script feature,
> it would be near impossible to get certain things done. It's sort of
> the equivalent of plug-in filters for a graphics programs.
It has been proven that XSLT is a Turing-complete language. This means that
it is in the group of the most powerful languages and if a problem can be
solved in any other language, it can be solved in XSLT, too (if all
necessary inputs can be provided).
User-written extension functions are rarely necessary. They can be harmful
in the cases when an extension function has side effects. This is why using
extension functions is not recommended in the general case.
On the other side, using extension functions with no side effects is
harmless, its only drawback being that it defeats the portability of the
xslt code.
> I notice the fxsl uses no xsl:script?
Right. FXSL is pure XSLT 1.0 (with the notable exception of the
xxx:node-set() function) and wil be 100% pure in XSLT 2.0.
>"Mark Johnson" <1023...@compuserve.com> wrote in message
>news:79otavkpvsvn4iuks...@4ax.com...
>It has been proven that XSLT is a Turing-complete language. This means that
>it is in the group of the most powerful languages and if a problem can be
>solved in any other language, it can be solved in XSLT, too (if all
>necessary inputs can be provided).
Just as example, here's the last thing I needed to add to my template.
I was just going to copy over and translate into either vbscript or
jscript (I don't think msxml3 supports javascript - it crashed when I
tried "alert()"). Could this really be performed using just xslt?
Maybe not the cleanest code. But it basically works. Lots of clumsy
string handling and RegExp calls.
' Given a relative path - e.g. "../../img/x.gif" - find the new relative path if image, or whatever, isn't moved.
' From the source template, replace all instances in the target file so it will work at the target location.
' Assumption, here, is that the target and source paths are just directories, and don't include a trailing file name.
' However, if a period/dot is found following the last slash, then everything after the last slash is trimmed from the path.
' The optional ignoreTrim flag can be set to true to prevent this.
Public Function fGetRelURL(ByVal strFullTargetPath As String, ByVal strFullSourcePath As String, _
Optional ByVal strRelPath As String, Optional ysnIgnoreTrim As Boolean)
' offs looks ahead, and the latch holds the previous offset
Dim offs, offsLatch, dum
Dim strDotPath As String, strMidPath As String, strCheck As String
Dim regExp2 As New RegExp
regExp2.Global = True
' Backslash is special reg expr char, so double up.
' The loops below assume only forward slashes are used. Make the change here.
regExp2.Pattern = "\\"
strRelPath = regExp2.replace(strRelPath, "/")
strFullTargetPath = regExp2.replace(strFullTargetPath, "/")
strFullSourcePath = regExp2.replace(strFullSourcePath, "/")
If Not ysnIgnoreTrim Then
' Save first to variable, because the arg to fStripRightDir is changed.
strCheck = strFullTargetPath
If InStr(fStripRightDir(strCheck), ".") Then strFullTargetPath = strCheck
strCheck = strFullSourcePath
If InStr(fStripRightDir(strCheck), ".") Then strFullSourcePath = strCheck
End If
' kill all leading slashes or dots
regExp2.Pattern = "^/+"
strRelPath = regExp2.replace(strRelPath, "")
If Left(strRelPath, 2) = "./" Then strRelPath = Mid(strRelPath, 3)
offs = 1
offsLatch = 1
Do While offs < Len(strFullTargetPath)
' look ahead
offs = InStr(offs, strFullTargetPath, "/")
If offs < 1 Then
Exit Do
Else
If Left(strFullTargetPath, offs) <> Left(strFullSourcePath, offs) Then
Exit Do
End If
End If
offsLatch = offs
offs = offs + 1
Loop
If Len(strFullSourcePath) > 0 Then
strMidPath = Right(strFullSourcePath, Len(strFullSourcePath) - offsLatch)
End If
If offsLatch < Len(strFullTargetPath) Then
strDotPath = Right(strFullTargetPath, Len(strFullTargetPath) - offsLatch)
regExp2.Pattern = "[^/]*/"
strDotPath = regExp2.replace(strDotPath, "../")
End If
Do
If Left(strRelPath, 3) = "../" Then
strRelPath = Right(strRelPath, Len(strRelPath) - 3)
strDotPath = "../" & strDotPath
dum = fStripRightDir(strMidPath)
Else
Exit Do
End If
Loop
fGetRelURL = "./" & strDotPath & strMidPath & strRelPath
End Function
>"Dimitre Novatchev" <dnova...@yahoo.com> wrote:
>
>>"Mark Johnson" <1023...@compuserve.com> wrote in message
>>news:79otavkpvsvn4iuks...@4ax.com...
>
>>It has been proven that XSLT is a Turing-complete language. This means that
>>it is in the group of the most powerful languages and if a problem can be
>>solved in any other language, it can be solved in XSLT, too (if all
>>necessary inputs can be provided).
>
>Just as example, here's the last thing I needed to add to my template.
> I was just going to copy over and translate into either vbscript or
> jscript (I don't think msxml3 supports javascript - it crashed when I
> tried "alert()"). Could this really be performed using just xslt?
Probably should have included the following, to avoid confusion:
My mistake.
' Strip everything from strPath following the last forward or
' back slash, including the slash.
' This will strip a trailing slash, and if there are none remaining,
' it wil set strPath to ""
' The ByRef strPath is modified on exit, to the path without the
' last file or string (anything past the last slash).
' But the function returns that bit which was sliced off.
Public Function fStripRightDir(strPath As String)
Dim offs, strCh As String, strWork As String
Dim regExp1 As New RegExp
' Change backslashes to forward slashes, to remove extra tests
' But don't change strPath, itself, in this way.
strWork = strPath
regExp1.Global = True
' backslash is special reg expr char, so double up
regExp1.Pattern = "\\"
strWork = regExp1.replace(strWork, "/")
If Right(strWork, 1) = "/" Then strWork = Left(strWork,
Len(strWork) - 1)
If InStr(strWork, "/") < 1 Then
strPath = ""
fStripRightDir = ""
Exit Function
End If
offs = Len(strWork) + 1
Do While offs > 0
offs = offs - 1
If Mid(strWork, offs, 1) = "/" Then Exit Do
Loop
strPath = Left(strPath, offs)
fStripRightDir = Right(strWork, Len(strWork) - offs)
End Function
As far as the rest, I think it could indeed be done more easily in XSLT.
The translate() function will easily change backslashes to forward slashes.
But, if you're going to do complicated string manipulation, you can justify
using msxsl:script, as long as you don't create side effects. I'm sure
Dimitre will come up with a pure XSLT solution that will, as usual, make my
jaw drop! ;^)
Regards,
Mike Sharp
"Mark Johnson" <1023...@compuserve.com> wrote in message
news:rp4uavki45pdpc7ma...@4ax.com...
>As far as the rest, I think it could indeed be done more easily in XSLT.
>The translate() function will easily change backslashes to forward slashes.
>But, if you're going to do complicated string manipulation, you can justify
>using msxsl:script, as long as you don't create side effects. I'm sure
>Dimitre will come up with a pure XSLT solution that will, as usual, make my
>jaw drop! ;^)
So the translate can substitute for most simple RegExp? There's the
all characters after, whitespace, and so. But I'll read on translate
and see what it can do.
Still, you'd have all the variables, substring manipulation - messy as
it is (and I don't imply that this is the best or optimized algorithm,
just one that sort of works, is all). And then you have all the built
in object calls. Could that be done in an xsl tag?
Obviously, _I_ don't know. But reading xslt stuff on the web, you
don't get the sense of any of that.
| This page has been accesed many thousands times and I'm glad now we have
| the first remark that it is not completely understandable.
I, however, found them just about unreadable. Tag syntax is bad enough
as it is, but the padding of syntactic attribute values with leading and
trailing white space (including newlines) made it all the worse.
You are again the first to say so -- many people actually have praised
highly the presentation of the code, calling it "extremely cool".
Let me guess -- is your browser Netscape 3 or older?
| many people actually have praised highly the presentation of the code,
| calling it "extremely cool".
I hope you at least used a program to generate such extreme coolness,
rather than create such hostile markup by hand.
| Let me guess -- is your browser Netscape 3 or older?
It isn't Netscape, and it's newer. The extreme coolness was lost to me
because I configure my browser to ignore <FONT>. Toggling stylesheets
got rid of the extraneous newlines, though.
(You do realize, I hope, that <XMP> was deprecated eons ago? I think
you wanted <TT>, but that's just a detail.)
Reverting to the subject matter, however: once I got past the formatting
I found the material quite fascinating.
No, not by hand -- this is what XSelerator's display looks like.
> Reverting to the subject matter, however: once I got past the formatting
> I found the material quite fascinating.
Thanks for this appreciation.
However, I don't understand the problem at all.
Could you, please, specify:
1. The input (e.g. two concrete filepaths)
2. What is the desired output -- again a concrete result that must be
obtained
3. What the transformation must do -- some general desired properties, so
that the transformation will do the same good job on other inputs.
=====
Cheers,
Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
"Mark Johnson" <1023...@compuserve.com> wrote in message
news:i63uavg9uf24pum3n...@4ax.com...
>Most probably there is an XSLT solution.
>
>However, I don't understand the problem at all.
>
>Could you, please, specify:
>
>1. The input (e.g. two concrete filepaths)
On a file server, in this case, but could be any path. So the drive,
path, but also with a possible filename at the end which has to go.
So you know the full path of the template file. You know what is going
to be the path for the output/target file. And you have the relative
path in the template, that has to be modified, and the new path used
in that same place, in the target.
>2. What is the desired output -- again a concrete result that must be
>obtained
As described there, it's thought of as a template; an HTML doc with
'holes', asp/cgi calls, to fill in those sections with strings and
other HTML tags. The template might have some relative paths to images
or HD links, buttons, boilerplate, and so on. But the template can be
applied to any directory on disk. The new file, based on the template,
would not duplicate these images or links, but refer to them where
they are. So the source, template, paths would have to be modified to
reflect the new target position. That would be the 'direction' in
which it works.
Please:
1. give an exact string -- e.g. "c:/xxx/yyy/zzz/ttt.html -- this is the
current file-path
2. give another exact string -- e.g. d:/aaa/bbb/ccc -- this is the
desired new file path
You have not given *any* concrete example!!!
How can you expect that someone will help? What you described until now is
not understandable at all.
"Mark Johnson" <1023...@compuserve.com> wrote in message
news:5ec0bvgsncbj1v5pa...@4ax.com...
>You didn't provide any useful info.
>Please:
>1. give an exact string -- e.g. "c:/xxx/yyy/zzz/ttt.html -- this is the
>current file-path
>2. give another exact string -- e.g. d:/aaa/bbb/ccc -- this is the
>desired new file path
>You have not given *any* concrete example!!!
Sorry.
Source, as you say above, c:/x/t/z/ or c:/x/t/z/abc.gif
Target, c:/x/t/z/a/ or c:/x/ or e: or f:/a/b/
String to modify, ../../img/one.jpg, or ./img/one/two.gif, or /ate.gif
In the procedure I posted, it takes a full path for the source, full
path for target, and the relative path to modify (along with that one
override flag).
Example:
So "../../img/one.jpg",
found in a html 'template' file at, "c:/x/t/u/tmp1.htm"
(which refers, i.e., to "one.jpg" at "c:/x/img/one.jpg")
is going to be copied and modified for a target file at,
"c:/x/place/targ.htm", based on the tmp1 'template'.
That means this string,
"../../img/one.jpg",
found in, "c:/x/t/u/tmp1.htm"
must be changed to,
"../img/one.jpg", when copied to targ.htm.
So the procedure just basically turns,
"../../img/one.jpg", the string,
into the string,
"../img/one.jpg", in this case.
In my routine, all the relative strings are isolated in a table, and
the routine which called the one that I posted is reading from that
table. But in xslt, I would think the string, itself, would be passed
to a routine.
Some input conditions:
1) the slashes could be forward or back, or mixed.
I converted all to forward, to avoid extra testing.
2) The relative path which is to be modified might be prefixed with
"./" or assorted "///", "/", etc., which I remove.
3) perhaps either of the source or target might also have a filename
attached, which I remove (though not to modify by reference that which
was passed-in). The assumption, however, is that a filename is
indicated by a dot, period, somewhere in the substring, in the
filename. And not all files have an extension. Without one, it's
treated as a directory name. Would be up to calling routine to handle
that.
>>You have not given *any* concrete example!!!
>Sorry.
Sorry, again. Forgot the xml.
The target and source paths would be the same for the whole xml file.
So I could see
<project>
<fullsrcpath>....
<fulltargpath>....
</project>
And these could be then referred to when a specific path is up for
modification.
Hi Mark,
Using FXSL one would write something like this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:mySelect="f:mySelectLoc"
exclude-result-prefixes="msxsl mySelect"
>
<xsl:import href="..\Generic\FP\Fxsl\Msxsl\strSplit-to-Words.xsl"/>
<xsl:import href="..\Generic\FP\Fxsl\Msxsl\dropWhile.xsl"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vrtfAbsPath">
<xsl:call-template name="getAbsPath">
<xsl:with-param name="pPath" select="/*/app/@path"/>
<xsl:with-param name="pRef" select="/*/app/fileRef"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vAbsPath"
select="msxsl:node-set($vrtfAbsPath)/*"/>
<xsl:variable name="vrtfNewPath">
<xsl:call-template name="str-split-to-words">
<xsl:with-param name="pStr" select="/*/app/@newpath"/>
<xsl:with-param name="pDelimiters" select="'/\'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vNewPath"
select="msxsl:node-set($vrtfNewPath)/*"/>
<xsl:choose>
<xsl:when test="not($vAbsPath[1] = $vNewPath[1])">
<xsl:call-template name="genRelPath">
<xsl:with-param name="pLocations" select="$vAbsPath"/>
<xsl:with-param name="pStartingSame" select="0"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vFunSelect"
select="document('')/*/mySelect:*[1]"/>
<xsl:variable name="vrtfAbsTail">
<xsl:call-template name="dropWhile">
<xsl:with-param name="pList" select="$vAbsPath[position() >
1]"/>
<xsl:with-param name="pController" select="$vFunSelect"/>
<xsl:with-param name="pContollerParam"
select="$vNewPath[position() > 1]"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vcntLeadingSameLocs"
select="count($vAbsPath)
-
count(msxsl:node-set($vrtfAbsTail)/*)
- 1 "/>
<xsl:call-template name="genRelPath">
<xsl:with-param name="pLocations"
select="$vAbsPath[position() > 1]"/>
<xsl:with-param name="pStartingSame"
select="$vcntLeadingSameLocs"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="genRelPath">
<xsl:param name="pLocations" select="/.."/>
<xsl:param name="pStartingSame"/>
<xsl:for-each select="$pLocations
[position() <= $pStartingSame]">
<xsl:text>../</xsl:text>
</xsl:for-each>
<xsl:for-each select="$pLocations
[position() > $pStartingSame]">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">/</xsl:if>
</xsl:for-each>
</xsl:template>
<mySelect:mySelect/>
<xsl:template match="mySelect:*">
<xsl:param name="pList" select="/.."/> <!-- current lidt-node -->
<xsl:param name="pParams" select="/.."/><!-- The second list -->
<xsl:variable name="vPos"
select="count($pList/preceding-sibling::*)"/>
<xsl:if test="$pList = $pParams[position() = $vPos]">1</xsl:if>
</xsl:template>
<xsl:template name="getAbsPath">
<xsl:param name="pPath"/>
<xsl:param name="pRef"/>
<xsl:variable name="vrtfPathParts">
<xsl:call-template name="str-split-to-words">
<xsl:with-param name="pStr" select="$pPath"/>
<xsl:with-param name="pDelimiters" select="'/\'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vPathParts"
select="msxsl:node-set($vrtfPathParts)/word"/>
<xsl:variable name="vrtfRefParts">
<xsl:call-template name="str-split-to-words">
<xsl:with-param name="pStr" select="$pRef"/>
<xsl:with-param name="pDelimiters" select="'/\'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vRefParts"
select="msxsl:node-set($vrtfRefParts)/word"/>
<xsl:variable name="vpathAbsParts"
select="$vPathParts
[position()
<
last() - count($vRefParts[. = '..'])]"/>
<xsl:variable name="vrefAbsParts"
select="$vRefParts[not(. = '..')]"/>
<xsl:copy-of select="$vpathAbsParts"/>
<xsl:copy-of select="$vrefAbsParts"/>
</xsl:template>
</xsl:stylesheet>
When applied on this source.xml:
<reloc>
<app path="c:/x/t/u/tmp1.htm"
newpath="c:/x/place/targ.htm"
>
<fileRef>../../img/one.jpg</fileRef>
</app>
</reloc>
the wanted result is produced:
../img/one.jpg
First I am generating a node-set, consisting of all tokens (location steps)
that the absolute file-path must have. It looks like this:
<word>c:</word>
<word>x</word>
<word>img</word>
<word>one.jpg</word>
Then I'm splitting into separate tokens (location paths) the new file-path.
It looks like:
<word>c:</word>
<word>x</word>
<word>place</word>
<word>targ.htm</word>
To do this I'm using the FXSL template "str-split-to-words", which produces
a list of tokens in the above form, given a string and a list of possible
delimiters.
Then I'm using the FXSL template "dropWhile", passing to it the list of
locations of the abs.path, the list of locations of the new-path and a
function (actually a reference to a template) that controls until when to
drop elements from the first list.
The result is a tail of the abs.list, consisting of locations that must be
added at the end of the new relative path.
Finally, the template "genRelPath" takes a list of nodes (node-set)
"pLocations" and a number "pStartingSame" . It outputs "../" pStartingSame
number of times, then the rest of the nodes in "pLocations".
I hope this illustrates well the power of using FXSL. Solving this problem
took me 20-30 minutes.
>"Mark Johnson" <1023...@compuserve.com> wrote in message
>news:f6f0bvc0f0i9hnvm1...@4ax.com...
>> So "../../img/one.jpg",
>> found in a html 'template' file at, "c:/x/t/u/tmp1.htm"
>> (which refers, i.e., to "one.jpg" at "c:/x/img/one.jpg")
>> is going to be copied and modified for a target file at,
>> "c:/x/place/targ.htm", based on the tmp1 'template'.
>> That means this string,
>> "../../img/one.jpg",
>> found in, "c:/x/t/u/tmp1.htm"
>> must be changed to,
>> "../img/one.jpg", when copied to targ.htm.
>Hi Mark,
>Using FXSL one would write something like this:
. . .
>I hope this illustrates well the power of using FXSL. Solving this problem
>took me 20-30 minutes.
It does. This xslt is making a little more sense to me, as well -
though I can't say I can really speak on it, or understand it. It's
not necessarily more complicated, either, than the vb code I came up
with. But I did leave off all the input filtering stuff, which I don't
think I included there. The procedure I posted, previously, like the
one you posted, only solved the problem for a certain limited subset.
This is what I found for a more general solution to the problem:
.xml file:
<root>
<file>
<sourcepath>c:/x/y/r/h</sourcepath>
<targetpath>c:/x/y/w/t/</targetpath>
</file>
And I had wanted to just do a curdir or the like, so I wouldn't need
sourcepath. But I couldn't find any vbscript thing that would work,
not with fso or anything (not an xslt problem - but just btw). So I
have the db send the sourcepath as it creates the xml file.
called in .xsl:
select="ns:fGetRelURL(//file/*,"../common/img/b.gif"/>
And which, of course, produces: ../../r/common/img/b.gif
and in the .xsl, as a msxml:script, vbscript:
Function fGetRelURL(paths,strRelPath)
Dim offs, strDotPath, strMidPath, strCheck
Dim strFullSourcePath, strFullTargetPath, strOut
Dim regExp2
Set regExp2 = New RegExp
strFullSourcePath = paths.item(0).text
strFullTargetPath = paths.item(1).text
Btw, I never did figure how to pass a nodeset that would use the
selectsinglenode property, or even getelementsbytagname. I see this
example in a bunch of messages to these xml groups. But I couldn't get
it to work. I speculated it was sending the wrong sort of object, that
didn't have either as a method. But getelements is a common method. So
it should show up. I shouldn't get an object doesn't support, error.
' all the input preparation/'massaging'/'conditioning', etc
regExp2.Global = True
regExp2.Pattern = "\\"
strRelPath = regExp2.replace(strRelPath, "/")
strFullTargetPath = regExp2.replace(strFullTargetPath, "/")
strFullSourcePath = regExp2.replace(strFullSourcePath, "/")
strCheck = strFullTargetPath
If InStr(fStripRightDir(strCheck), ".") Then strFullTargetPath =
strCheck
sAppendIfNeeded strFullTargetPath, "/"
strCheck = strFullSourcePath
If InStr(fStripRightDir(strCheck), ".") Then strFullSourcePath =
strCheck
regExp2.Pattern = "^/+"
strRelPath = regExp2.replace(strRelPath, "")
If Left(strRelPath, 2) = "./" Then strRelPath = Mid(strRelPath, 3)
sAdjustRelPaths strFullSourcePath, strRelPath
sAppendIfNeeded strFullSourcePath, "/"
' end input preparation
offs = fUptoWhereStringsSame(strFullTargetPath, strFullSourcePath)
If offs < 1 Then
strOut = strFullTargetPath & strRelPath
Else
regExp2.Pattern = "[^/]*/"
strMidPath = Right(strFullTargetPath, Len(strFullTargetPath) -
offs)
strDotPath = regExp2.replace(strMidPath, "../")
strMidPath = Right(strFullSourcePath, Len(strFullSourcePath) -
offs)
strOut = "./" & strDotPath & strMidPath & strRelPath
End If
fGetRelURL = strOut
End Function
' removes everything right of last slash or forward slash
' changes strPath byref, but returns the bit trimmed off
Function fStripRightDir(strPath)
Dim offs, strCh, strWork
Dim regExp1
Set regExp1 = New RegExp
strWork = strPath
regExp1.Global = True
regExp1.Pattern = "\\"
strWork = regExp1.replace(strWork, "/")
If Right(strWork, 1) = "/" Then strWork = Left(strWork,
Len(strWork) - 1)
If InStr(strWork, "/") < 1 Then
strPath = ""
fStripRightDir = ""
Exit Function
End If
offs = Len(strWork) + 1
Do While offs > 0
offs = offs - 1
If Mid(strWork, offs, 1) = "/" Then Exit Do
Loop
strPath = Left(strPath, offs)
fStripRightDir = Right(strWork, Len(strWork) - offs)
End Function
Public Sub sAppendIfNeeded(strMod, strChar)
If Right(strMod, 1) <> strChar Then strMod = strMod & strChar
End Sub
' Slide the relpath 'over', as it were, removing "../" and trimming
' source/strRemoveRight, accordingly.
Public Sub sAdjustRelPaths(strRemoveRight, strRemoveLeft)
Dim dum
Do
If Left(strRemoveLeft, 3) = "../" Then
dum = fStripRightDir(strRemoveRight)
strRemoveLeft = Right(strRemoveLeft, Len(strRemoveLeft) -
3)
Else
Exit Do
End If
Loop
End Sub
' find the offs where str1 and str2 are no longer the same, reading
from left
Public Function fUptoWhereStringsSame(ByVal str1, ByVal str2)
Dim intCheck, ysnStr1Bigger, offs, i
' try and all at once check, at first
ysnStr1Bigger = Len(str1) > Len(str2)
intCheck = IIf(ysnStr1Bigger, InStr(str1, str2), InStr(str2,
str1))
If intCheck < 1 Then
If ysnStr1Bigger Then SwapIt str1, str2
For i = 1 To Len(str2)
If Mid(str1, i, 1) <> Mid(str2, i, 1) Then Exit For
Next
offs = i - 1
Else
offs = IIf(ysnStr1Bigger, Len(str2), Len(str1))
End If
fUptoWhereStringsSame = offs
End Function
Public Sub SwapIt(str1, str2)
Dim str3
str3 = str1
str1 = str2
str2 = str3
End Sub
And also an IIf, because vbscript doesn't have one.
I wondered if just putting Swapit, or the append, or very simple
functions like than in xslt might not be a good thing. I also had a
couple of dfield type procedures. But I thought just scanning
character by character would be simpler (but perhaps not if in xslt,
as you showed).
After having broken out the simpler stuff into separate routines, it
helped clarify the problem, for me. It seems more intuitive, and
easier to follow, as well. But for that advantage in the vb, I wonder
if it would necessarily be more complicated in xslt? especially for
the use of RegExp in this. But I see how you got around that in the
specifics, with that nodeset of 'tokens', and so on - + translate,
etc.
Might there be points where this 'declarative' language would
duplicate the procedural? For ex, the append is a substring test. That
would probably be just a test= is xslt, as well, correct? I would
assume the swap would be pretty easy, on 'built-in' in some way. And
so on. But anytime you're running a list (the above is almost a 'tape'
in the uptowhere comparison), it has to be 'tokenized'; has to be
transformed into nodes? And that would seem, to me, to be a little
different. On the other hand, maybe the reladjust would be, again,
just some substring manipulations, without having to break the
components into nodes?