[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] RE: Where is my document? local source path discovery
Wow Eliot - that is really useful, thanks. It took me a few minutes to read and understand but now I have, it has certainly saved me a great deal of time. Thanks very much. The missing piece of the puzzle then is to discover the local source path from within the source document while it is being processed. Once I have that, I'm home and dry! Does anyone have further ideas? Richard -----Original Message----- From: Eliot Kimber [mailto:ekimber@xxxxxxxxxxxx] Sent: 28 June 2008 13:52 To: xsl-list Subject: Re: XSLT 2 Functions for URL Manipulation (was Rewriting href) On 6/28/08 5:22 AM, "Marroc" <marrocdanderfluff@xxxxxxxxxxx> wrote: > Can anyone suggest an XSL technique or mechanism for taking either of > these types of dysfunctional path and making them into the > shortest-possible relative path? I think this demands that the XSLT is > aware of the location of the current document so that it can parse the > folder path, decide where it varies and rebuild it in a relative fashion. Here is an XSLT 2 function package for working with paths, specifically intended to solve the sort of URL rewriting problems you face (and in a DITA context no less), and a set of unit tests for it. --- cut here: relpath_util.xsl --- <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:local="http://www.example.com/functions/local" exclude-result-prefixes="local xs" > <xsl:function name="local:base-uri" as="xs:string"> <xsl:param name="context" as="node()"/> <xsl:variable name="baseUri" select="string(base-uri($context))" as="xs:string"/> <xsl:variable name="resultBaseUri" select="if (starts-with($baseUri, 'file:///')) then (concat('file:/', substring-after($baseUri, 'file:///'))) else $baseUri " as="xs:string"/> <xsl:sequence select="$resultBaseUri"/> </xsl:function> <xsl:function name="local:encodeUri" as="xs:string"> <xsl:param name="inUriString" as="xs:string"/> <xsl:variable name="temp1" as="xs:string" select="replace($inUriString, ' ', '%20')" /> <xsl:variable name="temp2" as="xs:string" select="replace($temp1, '\[', '%5B')" /> <xsl:variable name="temp3" as="xs:string" select="replace($temp2, '\]', '%5D')" /> <xsl:variable name="outUriString" as="xs:string" select="$temp3" /> <xsl:sequence select="$outUriString"/> </xsl:function> <xsl:function name="local:getName" as="xs:string"> <!-- As for Java File.getName(): returns the last component of the path. --> <xsl:param name="sourcePath" as="xs:string"/> <xsl:value-of select="tokenize($sourcePath, '/')[last()]"/> </xsl:function> <xsl:function name="local:getNamePart" as="xs:string"> <!-- Returns the name part of a filename, excluding any trailing extension. --> <xsl:param name="sourcePath" as="xs:string"/> <xsl:variable name="fullName" select="local:getName($sourcePath)" as="xs:string"/> <xsl:variable name="result" as="xs:string" select="if (contains($fullName, '.')) then string-join(tokenize($fullName, '\.')[position() < last()], '.') else $fullName " /> <xsl:value-of select="$result"/> </xsl:function> <xsl:function name="local:getExtension" as="xs:string"> <!-- Returns the extension part of a filename, excluding the leading "." --> <xsl:param name="sourcePath" as="xs:string"/> <xsl:variable name="fullName" select="local:getName($sourcePath)" as="xs:string"/> <xsl:variable name="result" as="xs:string" select="if (contains($fullName, '.')) then tokenize($fullName, '\.')[last()] else '' " /> <xsl:value-of select="$result"/> </xsl:function> <xsl:function name="local:getParent" as="xs:string"> <!-- As for Java File.getParent(): returns all but the last components of the path. --> <xsl:param name="sourcePath" as="xs:string"/> <xsl:value-of select="string-join(tokenize($sourcePath, '/')[position() < last()], '/')"/> </xsl:function> <xsl:function name="local:newFile" as="xs:string"> <!-- As for Java File(File, path)): Returns a new a absolute path representing the new file. File must be a path (because XSLT has no way to distinguish a file from a directory). --> <xsl:param name="parentPath" as="xs:string"/> <xsl:param name="childFile" as="xs:string"/> <xsl:choose> <xsl:when test="matches($childFile, '^(/|[a-z]+:)')"> <xsl:value-of select="$childFile"/> </xsl:when> <xsl:when test="$parentPath = '/'"> <xsl:variable name="tempPath" select="concat($parentPath, $childFile)" as="xs:string"/> <xsl:variable name="result" select="local:getAbsolutePath($tempPath)"/> <xsl:value-of select="$result"/> </xsl:when> <xsl:otherwise> <xsl:variable name="tempParentPath" as="xs:string" select="if (ends-with($parentPath, '/') and $parentPath != '/') then substring($parentPath, 1, string-length($parentPath) - 1) else $parentPath" /> <xsl:variable name="parentTokens" select="tokenize($tempParentPath, '/')" as="xs:string*"/> <xsl:variable name="childTokens" select="tokenize($childFile, '/')" as="xs:string*"/> <xsl:variable name="tempPath" select="string-join(($parentTokens, $childTokens), '/')" as="xs:string"/> <xsl:variable name="result" select="local:getAbsolutePath($tempPath)"/> <xsl:value-of select="$result"/> </xsl:otherwise> </xsl:choose> </xsl:function> <xsl:function name="local:getAbsolutePath" as="xs:string"> <!-- Given a path resolves any ".." or "." terms to produce an absolute path --> <xsl:param name="sourcePath" as="xs:string"/> <xsl:variable name="pathTokens" select="tokenize($sourcePath, '/')" as="xs:string*"/> <xsl:if test="false()"> <xsl:message> + DEBUG local:getAbsolutePath(): Starting</xsl:message> <xsl:message> + sourcePath="<xsl:value-of select="$sourcePath"/>"</xsl:message> </xsl:if> <xsl:variable name="baseResult" select="string-join(local:makePathAbsolute($pathTokens, ()), '/')" as="xs:string"/> <xsl:variable name="baseResult2" select="if (ends-with($baseResult, '/')) then substring($baseResult, 1, string-length($baseResult) -1) else $baseResult" as="xs:string"/> <xsl:variable name="result" as="xs:string" select="if (starts-with($sourcePath, '/') and not(starts-with($baseResult2, '/'))) then concat('/', $baseResult2) else $baseResult2 " /> <xsl:if test="false()"> <xsl:message> + DEBUG: result="<xsl:value-of select="$result"/>"</xsl:message> </xsl:if> <xsl:value-of select="$result"/> </xsl:function> <xsl:function name="local:makePathAbsolute" as="xs:string*"> <xsl:param name="pathTokens" as="xs:string*"/> <xsl:param name="resultTokens" as="xs:string*"/> <xsl:if test="false()"> <xsl:message> + DEBUG: local:makePathAbsolute(): Starting...</xsl:message> <xsl:message> + DEBUG: pathTokens="<xsl:value-of select="string-join($pathTokens, ',')"/>"</xsl:message> <xsl:message> + DEBUG: resultTokens="<xsl:value-of select="string-join($resultTokens, ',')"/>"</xsl:message> </xsl:if> <xsl:sequence select="if (count($pathTokens) = 0) then $resultTokens else if ($pathTokens[1] = '.') then local:makePathAbsolute($pathTokens[position() > 1], $resultTokens) else if ($pathTokens[1] = '..') then local:makePathAbsolute($pathTokens[position() > 1], $resultTokens[position() < last()]) else local:makePathAbsolute($pathTokens[position() > 1], ($resultTokens, $pathTokens[1])) "/> </xsl:function> <xsl:function name="local:getRelativePath" as="xs:string"> <!-- Calculate relative path that gets from from source path to target path. Given: [1] Target: /A/B/C Source: /A/B/C/X Return: "X" [2] Target: /A/B/C Source: /E/F/G/X Return: "/E/F/G/X" [3] Target: /A/B/C Source: /A/D/E/X Return: "../../D/E/X" [4] Target: /A/B/C Source: /A/X Return: "../../X" --> <xsl:param name="source" as="xs:string"/><!-- Path to get relative path *from* --> <xsl:param name="target" as="xs:string"/><!-- Path to get relataive path *to* --> <xsl:if test="false()"> <xsl:message> + DEBUG: local:getRelativePath(): Starting...</xsl:message> <xsl:message> + DEBUG: source="<xsl:value-of select="$source"/>"</xsl:message> <xsl:message> + DEBUG: target="<xsl:value-of select="$target"/>"</xsl:message> </xsl:if> <xsl:variable name="sourceTokens" select="tokenize((if (starts-with($source, '/')) then substring-after($source, '/') else $source), '/')" as="xs:string*"/> <xsl:variable name="targetTokens" select="tokenize((if (starts-with($target, '/')) then substring-after($target, '/') else $target), '/')" as="xs:string*"/> <xsl:choose> <xsl:when test="(count($sourceTokens) > 0 and count($targetTokens) > 0) and (($sourceTokens[1] != $targetTokens[1]) and (contains($sourceTokens[1], ':') or contains($targetTokens[1], ':')))"> <!-- Must be absolute URLs with different schemes, cannot be relative, return target as is. --> <xsl:value-of select="$target"/> </xsl:when> <xsl:otherwise> <xsl:variable name="resultTokens" select="local:analyzePathTokens($sourceTokens, $targetTokens, ())" as="xs:string*"/> <xsl:variable name="result" select="string-join($resultTokens, '/')" as="xs:string"/> <xsl:value-of select="$result"/> </xsl:otherwise> </xsl:choose> </xsl:function> <xsl:function name="local:analyzePathTokens" as="xs:string*"> <xsl:param name="sourceTokens" as="xs:string*"/> <xsl:param name="targetTokens" as="xs:string*"/> <xsl:param name="resultTokens" as="xs:string*"/> <xsl:if test="false()"> <xsl:message> + DEBUG: local:analyzePathTokens(): Starting...</xsl:message> <xsl:message> + DEBUG: sourceTokens=<xsl:value-of select="string-join($sourceTokens, ',')"/></xsl:message> <xsl:message> + DEBUG: targetTokens=<xsl:value-of select="string-join($targetTokens, ',')"/></xsl:message> <xsl:message> + DEBUG: resultTokens=<xsl:value-of select="string-join($resultTokens, ',')"/></xsl:message> </xsl:if> <xsl:choose> <xsl:when test="count($sourceTokens) = 0"> <!-- Append remaining target tokens (if any) to the result --> <xsl:sequence select="$resultTokens, $targetTokens"/> </xsl:when> <xsl:otherwise> <!-- Still source tokens, so see if source[1] = target[1] --> <xsl:choose> <!-- If they are equal, go to the next level in the paths: --> <xsl:when test="(count($targetTokens) > 0) and ($sourceTokens[1] = $targetTokens[1])"> <xsl:sequence select="local:analyzePathTokens($sourceTokens[position() > 1], $targetTokens[position() > 1], $resultTokens)"/> </xsl:when> <xsl:otherwise> <!-- Paths must diverge at this point. Append one ".." for each token left in the source: --> <xsl:variable name="goUps" as="xs:string*"> <xsl:for-each select="$sourceTokens"> <xsl:sequence select="'..'"/> </xsl:for-each> </xsl:variable> <xsl:sequence select="string-join(($resultTokens, $goUps, $targetTokens), '/')"/> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:function> </xsl:stylesheet> --- cut here: relpath_util_test.xsl: --- <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:local="http://www.example.com/functions/local" exclude-result-prefixes="local xs" > <xsl:include href="../../ldist/xslt/relpath_util.xsl"/> <!-- Tests for the relpath_util functions --> <xsl:template match="/"> <!-- <xsl:call-template name="testEncodeUrl"/> <xsl:call-template name="testGetAbsolutePath"/> --> <xsl:call-template name="testGetRelativePath"/> <!-- <xsl:call-template name="testGetName"/> <xsl:call-template name="testGetParent"/> <xsl:call-template name="testNewFile"/> <xsl:call-template name="testGetNamePart"/> <xsl:call-template name="testGetExtension"/> --> </xsl:template> <xsl:template name="testEncodeUrl"> <xsl:variable name="testData" as="element()"> <test_data> <title>encodeUrl() Tests</title> <test> <source>/</source> <result>/</result> </test> <test> <source>/A B/C</source> <result>/A%20B/C</result> </test> <test> <source>/A[B]/D/foo.bar#e</source> <result>/A%5BB%5D/D/foo.bar#e</result> </test> </test_data> </xsl:variable> <xsl:apply-templates select="$testData" mode="testEncodeUrl"/> </xsl:template> <xsl:template name="testGetAbsolutePath"> <xsl:variable name="testData" as="element()"> <test_data> <title>getAbsolutePath() Tests</title> <test> <source>/</source> <result>/</result> </test> <test> <source>/A</source> <result>/A</result> </test> <test> <source>/A/..</source> <result>/</result> </test> <test> <source>/A/./B</source> <result>/A/B</result> </test> <test> <source>/A/B/C/D/../../E</source> <result>/A/B/E</result> </test> <test> <source>/A/B/C/D/../../E/F</source> <result>/A/B/E/F</result> </test> <test> <source>file:///A/B/C</source> <result>file:///A/B/C</result> </test> <test> <source>./A/B/C/D/E.xml</source> <result>A/B/C/D/E.xml</result> </test> <test> <source>/A/B/</source> <result>/A/B</result> </test> </test_data> </xsl:variable> <xsl:apply-templates select="$testData" mode="testGetAbsolutePath"/> </xsl:template> <xsl:template name="testGetRelativePath"> <xsl:variable name="testData" as="element()"> <test_data> <title>getRelativePath() Tests</title> <test> <source>/</source> <target>/A</target> <result>A</result> </test> <test> <source>/A</source> <target>/</target> <result>..</result> </test> <test> <source>/A</source> <target>/B</target> <result>../B</result> </test> <test> <source>/A</source> <target>/A/B</target> <result>B</result> </test> <test> <source>/A/B/C/D</source> <target>/A</target> <result>../../..</result> </test> <test> <source>/A/B/C/Z/Y</source> <target>/A/B/C/Y/Z</target> <result>../../Y/Z</result> </test> <test> <source>/A/B/C/D</source> <target>/A/E</target> <result>../../../E</result> </test> <test> <source>/A/B/C/D.xml</source> <target>/A/E</target> <result>../../E</result> <comment>This test should fail because there's no way for the XSLT to know that D.xml is a file and not a directory. The source parameter to relpath must be a directory path, not a filename.</comment> </test> <test> <source>/A/B</source> <target>/A/C/D</target> <result>../C/D</result> </test> <test> <source>/A/B/C</source> <target>/A/B/C/D/E</target> <result>D/E</result> </test> <test> <source>file:///A/B/C</source> <target>http://A/B/C/D/E</target> <result>http://A/B/C/D/E</result> </test> <test> <source>file://A/B/C</source> <target>file://A/B/C/D/E.xml</target> <result>D/E.xml</result> </test> </test_data> </xsl:variable> <xsl:apply-templates select="$testData" mode="testGetRelativePath"/> </xsl:template> <xsl:template match="test_data" mode="#all"> <test_results> <xsl:apply-templates mode="#current"/> </test_results> </xsl:template> <xsl:template name="testGetName"> <xsl:variable name="testData" as="element()"> <test_data> <title>getName() Tests</title> <test> <source>/</source> <result></result> </test> <test> <source>/A</source> <result>A</result> </test> <test> <source>/A/B</source> <result>B</result> </test> <test> <source>/A/B/C/D</source> <result>D</result> </test> </test_data> </xsl:variable> <xsl:apply-templates select="$testData" mode="testGetName"/> </xsl:template> <xsl:template name="testGetParent"> <xsl:variable name="testData" as="element()"> <test_data> <title>getParent() Tests</title> <test> <source>/</source> <result></result> </test> <test> <source>/A</source> <result></result> </test> <test> <source>/A/B</source> <result>/A</result> </test> <test> <source>/A/B/C/D</source> <result>/A/B/C</result> </test> </test_data> </xsl:variable> <xsl:apply-templates select="$testData" mode="testGetParent"/> </xsl:template> <xsl:template name="testNewFile"> <xsl:variable name="testData" as="element()"> <test_data> <title>newFile() Tests</title> <test> <parent>/</parent> <child>A</child> <result>/A</result> </test> <test> <parent>/A/B</parent> <child>C</child> <result>/A/B/C</result> </test> <test> <parent>/A/B</parent> <child>file://C</child> <result>file://C</result> </test> <test> <parent>/A/B</parent> <child>/C</child> <result>/C</result> </test> <test> <parent>/A/B</parent> <child>../C</child> <result>/A/C</result> </test> <test> <parent>/A/B</parent> <child>./C</child> <result>/A/B/C</result> </test> </test_data> </xsl:variable> <xsl:apply-templates select="$testData" mode="testNewFile"/> </xsl:template> <xsl:template name="testGetNamePart"> <xsl:variable name="testData" as="element()"> <test_data> <title>getNamePart() Tests</title> <test> <source>/</source> <result></result> </test> <test> <source>/A/B</source> <result>B</result> </test> <test> <source>/A/B/C.xml</source> <result>C</result> </test> <test> <source>/A/B/thisisalongname.foo</source> <result>thisisalongname</result> </test> </test_data> </xsl:variable> <xsl:apply-templates select="$testData" mode="testGetNamePart"/> </xsl:template> <xsl:template name="testGetExtension"> <xsl:variable name="testData" as="element()"> <test_data> <title>getExtension() Tests</title> <test> <source>/</source> <result></result> </test> <test> <source>/A/B</source> <result></result> </test> <test> <source>/A/B/C.xml</source> <result>xml</result> </test> <test> <source>/A/B/thisisalongname.foo</source> <result>foo</result> </test> <test> <source>/A/B/CCCC.</source> <result></result> </test> </test_data> </xsl:variable> <xsl:apply-templates select="$testData" mode="testGetExtension"/> </xsl:template> <xsl:template match="title" mode="#all"> <xsl:text>
</xsl:text> <xsl:value-of select="."/> <xsl:text>

</xsl:text> </xsl:template> <xsl:template match="test" mode="testGetExtension"> <xsl:text>Test Case: </xsl:text><xsl:number count="test" format="[1]"/><xsl:text>
</xsl:text> <xsl:text> source: "</xsl:text><xsl:value-of select="source"/><xsl:text>"
</xsl:text> <xsl:variable name="cand" select="local:getExtension(string(source))" as="xs:string"/> <xsl:variable name="pass" select="$cand = string(result)" as="xs:boolean"/> <xsl:text> result: "</xsl:text><xsl:value-of select="$cand"/><xsl:text>", pass: </xsl:text><xsl:value-of select="$pass"/><xsl:text>
</xsl:text> <xsl:if test="not($pass)"> <xsl:text> expected result: "</xsl:text><xsl:value-of select="result"/><xsl:text>"
</xsl:text> </xsl:if> <xsl:copy-of select="comment"/> <xsl:text>
</xsl:text> </xsl:template> <xsl:template match="test" mode="testGetNamePart"> <xsl:text>Test Case: </xsl:text><xsl:number count="test" format="[1]"/><xsl:text>
</xsl:text> <xsl:text> source: "</xsl:text><xsl:value-of select="source"/><xsl:text>"
</xsl:text> <xsl:variable name="cand" select="local:getNamePart(string(source))" as="xs:string"/> <xsl:variable name="pass" select="$cand = string(result)" as="xs:boolean"/> <xsl:text> result: "</xsl:text><xsl:value-of select="$cand"/><xsl:text>", pass: </xsl:text><xsl:value-of select="$pass"/><xsl:text>
</xsl:text> <xsl:if test="not($pass)"> <xsl:text> expected result: "</xsl:text><xsl:value-of select="result"/><xsl:text>"
</xsl:text> </xsl:if> <xsl:copy-of select="comment"/> <xsl:text>
</xsl:text> </xsl:template> <xsl:template match="test" mode="testGetName"> <xsl:text>Test Case: </xsl:text><xsl:number count="test" format="[1]"/><xsl:text>
</xsl:text> <xsl:text> source: "</xsl:text><xsl:value-of select="source"/><xsl:text>"
</xsl:text> <xsl:variable name="cand" select="local:getName(string(source))" as="xs:string"/> <xsl:variable name="pass" select="$cand = string(result)" as="xs:boolean"/> <xsl:text> result: "</xsl:text><xsl:value-of select="$cand"/><xsl:text>", pass: </xsl:text><xsl:value-of select="$pass"/><xsl:text>
</xsl:text> <xsl:if test="not($pass)"> <xsl:text> expected result: "</xsl:text><xsl:value-of select="result"/><xsl:text>"
</xsl:text> </xsl:if> <xsl:copy-of select="comment"/> <xsl:text>
</xsl:text> </xsl:template> <xsl:template match="test" mode="testGetParent"> <xsl:text>Test Case: </xsl:text><xsl:number count="test" format="[1]"/><xsl:text>
</xsl:text> <xsl:text> source: "</xsl:text><xsl:value-of select="source"/><xsl:text>"
</xsl:text> <xsl:variable name="cand" select="local:getParent(string(source))" as="xs:string"/> <xsl:variable name="pass" select="$cand = string(result)" as="xs:boolean"/> <xsl:text> result: "</xsl:text><xsl:value-of select="$cand"/><xsl:text>", pass: </xsl:text><xsl:value-of select="$pass"/><xsl:text>
</xsl:text> <xsl:if test="not($pass)"> <xsl:text> expected result: "</xsl:text><xsl:value-of select="result"/><xsl:text>"
</xsl:text> </xsl:if> <xsl:copy-of select="comment"/> <xsl:text>
</xsl:text> </xsl:template> <xsl:template match="test" mode="testGetAbsolutePath"> <xsl:text>Test Case: </xsl:text><xsl:number count="test" format="[1]"/><xsl:text>
</xsl:text> <xsl:text> source: "</xsl:text><xsl:value-of select="source"/><xsl:text>"
</xsl:text> <xsl:variable name="cand" select="local:getAbsolutePath(string(source))" as="xs:string"/> <xsl:variable name="pass" select="$cand = string(result)" as="xs:boolean"/> <xsl:text> result: "</xsl:text><xsl:value-of select="$cand"/><xsl:text>", pass: </xsl:text><xsl:value-of select="$pass"/><xsl:text>
</xsl:text> <xsl:if test="not($pass)"> <xsl:text> expected result: "</xsl:text><xsl:value-of select="result"/><xsl:text>"
</xsl:text> </xsl:if> <xsl:copy-of select="comment"/> <xsl:text>
</xsl:text> </xsl:template> <xsl:template match="test" mode="testGetRelativePath"> <xsl:text>Test Case: </xsl:text><xsl:number count="test" format="[1]"/><xsl:text>
</xsl:text> <xsl:text> source: "</xsl:text><xsl:value-of select="source"/><xsl:text>"
</xsl:text> <xsl:text> target: "</xsl:text><xsl:value-of select="target"/><xsl:text>"
</xsl:text> <xsl:variable name="cand" select="local:getRelativePath(string(source), string(target))" as="xs:string"/> <xsl:variable name="pass" select="$cand = string(result)" as="xs:boolean"/> <xsl:text> result: "</xsl:text><xsl:value-of select="$cand"/><xsl:text>", pass: </xsl:text><xsl:value-of select="$pass"/><xsl:text>
</xsl:text> <xsl:if test="not($pass)"> <xsl:text> expected result: "</xsl:text><xsl:value-of select="result"/><xsl:text>"
</xsl:text> </xsl:if> <xsl:copy-of select="comment"/> <xsl:text>
</xsl:text> </xsl:template> <xsl:template match="test" mode="testEncodeUrl"> <xsl:text>Test Case: </xsl:text><xsl:number count="test" format="[1]"/><xsl:text>
</xsl:text> <xsl:text> source: "</xsl:text><xsl:value-of select="source"/><xsl:text>"
</xsl:text> <xsl:text> target: "</xsl:text><xsl:value-of select="target"/><xsl:text>"
</xsl:text> <xsl:variable name="cand" select="local:encodeUri(string(source))" as="xs:string"/> <xsl:variable name="pass" select="$cand = string(result)" as="xs:boolean"/> <xsl:text> result: "</xsl:text><xsl:value-of select="$cand"/><xsl:text>", pass: </xsl:text><xsl:value-of select="$pass"/><xsl:text>
</xsl:text> <xsl:if test="not($pass)"> <xsl:text> expected result: "</xsl:text><xsl:value-of select="result"/><xsl:text>"
</xsl:text> </xsl:if> <xsl:copy-of select="comment"/> <xsl:text>
</xsl:text> </xsl:template> <xsl:template match="test" mode="testNewFile"> <xsl:text>Test Case: </xsl:text><xsl:number count="test" format="[1]"/><xsl:text>
</xsl:text> <xsl:text> parent: "</xsl:text><xsl:value-of select="parent"/><xsl:text>"
</xsl:text> <xsl:text> child: "</xsl:text><xsl:value-of select="child"/><xsl:text>"
</xsl:text> <xsl:variable name="cand" select="local:newFile(string(parent), string(child))" as="xs:string"/> <xsl:variable name="pass" select="$cand = string(result)" as="xs:boolean"/> <xsl:text> result: "</xsl:text><xsl:value-of select="$cand"/><xsl:text>", pass: </xsl:text><xsl:value-of select="$pass"/><xsl:text>
</xsl:text> <xsl:if test="not($pass)"> <xsl:text> expected result: "</xsl:text><xsl:value-of select="result"/><xsl:text>"
</xsl:text> </xsl:if> <xsl:copy-of select="comment"/> <xsl:text>
</xsl:text> </xsl:template> </xsl:stylesheet> --- end of transform --- Cheers, Eliot ---- Eliot Kimber | Senior Solutions Architect | Really Strategies, Inc. email: ekimber@xxxxxxxxxxxx <mailto:ekimber@xxxxxxxxxxxx> office: 610.631.6770 | cell: 512.554.9368 2570 Boulevard of the Generals | Suite 213 | Audubon, PA 19403 www.reallysi.com <http://www.reallysi.com> | http://blog.reallysi.com <http://blog.reallysi.com> | www.rsuitecms.com <http://www.rsuitecms.com>
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|