Question on " inside function arguments

D

David Furey

Hi

I have an XML documnet and a XSLT document as shown below

THe XSLT document brings back a filtered docmument that has the VendorName
that starts with a particular sub-string
This works as expected with alphabet and number characters and the ' (single
quote ' entity) character but does not work if a double quote character
" is part of the string to filter on
This returns all Vendor Names that begin with A (either case)

The XML Document

<?xml-stylesheet type="text/xsl" href="C:\XSL1.xsl"?>
<NEXXML xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<columns/>
<rows>
<row SAPVendorRef="15001" VendorName="A&quot; A Meats" EntityId="3021"
rsposition="1"/>
<row SAPVendorRef="57232" VendorName="Abbeyhouse Foods" EntityId="3050"
rsposition="2"/>
<row SAPVendorRef="15011" VendorName="Alexandra Rentals" EntityId="3023"
rsposition="3"/>
<row SAPVendorRef="10184" VendorName="Alexandra Workwear PLC"
EntityId="3014" rsposition="4"/>
<row SAPVendorRef="15012" VendorName="Allied Bakeries NI" EntityId="3024"
rsposition="5"/>
<row SAPVendorRef="60143" VendorName="Astron On Line" EntityId="3056"
rsposition="6"/>
<row SAPVendorRef="56531" VendorName="Backgammo'n" EntityId="3048"
rsposition="7"/>
<row SAPVendorRef="15062" VendorName="British Bakeries NI" EntityId="3025"
rsposition="8"/>
</rows>
</NEXXML>

The XSLT Document

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<xsl:eek:utput method="xml"/>
<xsl:template match="/">
<NEXXML>
<rows>
<xsl:apply-templates/>
</rows>
</NEXXML>
</xsl:template>
<xsl:template match="rows">
<xsl:apply-templates select="row"/>
</xsl:template>
<xsl:template match="row[ starts-with(translate(
@VendorName,&quot;abcdefghijklmnopqrstuvwxyz&quot;,&quot;ABCDEFGHIJKLMNOPQRS
TUVWXYZ&quot;),translate(&quot;A&quot;,&quot;abcdefghijklmnopqrstuvwxyz&quot
;,&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;)) ]">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>

If I want to search on the string A" the line

<xsl:template match="row[ starts-with(translate(
@VendorName,&quot;abcdefghijklmnopqrstuvwxyz&quot;,&quot;ABCDEFGHIJKLMNOPQRS
TUVWXYZ&quot;),translate(&quot;A&quot;,&quot;abcdefghijklmnopqrstuvwxyz&quot
;,&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;)) ]">
<xsl:copy-of select="."/>

changes to:

<xsl:template match="row[ starts-with(translate(
@VendorName,&quot;abcdefghijklmnopqrstuvwxyz&quot;,&quot;ABCDEFGHIJKLMNOPQRS
TUVWXYZ&quot;),translate(&quot;A&quot;&quot;,&quot;abcdefghijklmnopqrstuvwxy
z&quot;,&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;)) ]">
<xsl:copy-of select="."/>

I now get an error Expected token ')' found 'STRING'

From what I can see, this is because the XML parser reads the translate
function intereprets the 1st &quot; as the start of the first argument and
interprets the 2nd &quot; as the end of the 1st argument, instead of being
part of the first argument and then expects a comma (,) and the second
string argument

How I can make the parser take the 2nd quote as part of the first string
argument if there is a quote in the 1st argument
I know I could probably do this by replacing the double quotes with single
quotes but then I am assumming I will get the same problem with single
quotes been part of the literal string.

Your help is greatly appreciated. Thanks in advance

Regards David Furey
 
M

Marrow

Hi David,

In XPath strings can be delimited by either single (&apos;) or double
(&quot;) marks. So your template could read...

<xsl:template
match="row[starts-with(translate(@VendorName,'abcdefghijklmnopqrstuvwxyz','A
BCDEFGHIJKLMNOPQRSTUVWXYZ'),translate('A&quot;','abcdefghijklmnopqrstuvwxyz'
,'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))]">

Although using a template match for this is probably quite inefficient. For
two reasons...
i) because you are trying to do things in a template @match you cannot use
variables - which means that for every predicate [] filter evaluation you
are having to uppercase the string being searched for (i.e. that second
translate() call on 'A&quot;').
ii) also, because the filtering is being done at the template match, you are
sending out nodes that you are uninterested in - which are being caught by
the XSLT built-in rule templates (which may mean that if at some point in
the future your <row> elements have any text node children you may end up
with unexpected text in the output).

I assume at some point you are going to parameterize the search - at which
point using template matches for the filtering will become impossible. You
might want to try something like...

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<xsl:eek:utput method="xml"/>
<xsl:param name="search-for" select="'a&quot;'"/>
<!-- convert the param to upper case just once -->
<xsl:variable name="uc-search-for"
select="translate($search-for,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOP
QRSTUVWXYZ')"/>

<xsl:template match="/">
<NEXXML>
<rows>
<xsl:apply-templates/>
</rows>
</NEXXML>
</xsl:template>

<xsl:template match="rows">
<xsl:apply-templates
select="row[starts-with(translate(@VendorName,'abcdefghijklmnopqrstuvwxyz','
ABCDEFGHIJKLMNOPQRSTUVWXYZ'),$uc-search-for)]"/>
</xsl:template>

<xsl:template match="row">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>

Which, apart from making the code dynamic, will perform about twice as fast
as your original fixed stylesheet.

Hope this helps
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator


David Furey said:
Hi

I have an XML documnet and a XSLT document as shown below

THe XSLT document brings back a filtered docmument that has the VendorName
that starts with a particular sub-string
This works as expected with alphabet and number characters and the ' (single
quote &apos; entity) character but does not work if a double quote character
" is part of the string to filter on
This returns all Vendor Names that begin with A (either case)

The XML Document

<?xml-stylesheet type="text/xsl" href="C:\XSL1.xsl"?>
<NEXXML xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<columns/>
<rows>
<row SAPVendorRef="15001" VendorName="A&quot; A Meats" EntityId="3021"
rsposition="1"/>
<row SAPVendorRef="57232" VendorName="Abbeyhouse Foods" EntityId="3050"
rsposition="2"/>
<row SAPVendorRef="15011" VendorName="Alexandra Rentals" EntityId="3023"
rsposition="3"/>
<row SAPVendorRef="10184" VendorName="Alexandra Workwear PLC"
EntityId="3014" rsposition="4"/>
<row SAPVendorRef="15012" VendorName="Allied Bakeries NI" EntityId="3024"
rsposition="5"/>
<row SAPVendorRef="60143" VendorName="Astron On Line" EntityId="3056"
rsposition="6"/>
<row SAPVendorRef="56531" VendorName="Backgammo'n" EntityId="3048"
rsposition="7"/>
<row SAPVendorRef="15062" VendorName="British Bakeries NI" EntityId="3025"
rsposition="8"/>
</rows>
</NEXXML>

The XSLT Document

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<xsl:eek:utput method="xml"/>
<xsl:template match="/">
<NEXXML>
<rows>
<xsl:apply-templates/>
</rows>
</NEXXML>
</xsl:template>
<xsl:template match="rows">
<xsl:apply-templates select="row"/>
</xsl:template>
<xsl:template match="row[ starts-with(translate(
@VendorName,&quot;abcdefghijklmnopqrstuvwxyz&quot;,&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;),translate(&quot;A&quot;,&quot;abcdefghijklmnopqrstuvwxyz&quot
;,&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;)) ]">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>

If I want to search on the string A" the line

<xsl:template match="row[ starts-with(translate(
@VendorName,&quot;abcdefghijklmnopqrstuvwxyz&quot;,&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;),translate(&quot;A&quot;,&quot;abcdefghijklmnopqrstuvwxyz&quot
;,&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;)) ]">
<xsl:copy-of select="."/>

changes to:

<xsl:template match="row[ starts-with(translate(
@VendorName,&quot;abcdefghijklmnopqrstuvwxyz&quot;,&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;),translate(&quot;A&quot;&quot;,&quot;abcdefghijklmnopqrstuvwxy
z&quot;,&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;)) ]">
<xsl:copy-of select="."/>

I now get an error Expected token ')' found 'STRING'

From what I can see, this is because the XML parser reads the translate
function intereprets the 1st &quot; as the start of the first argument and
interprets the 2nd &quot; as the end of the 1st argument, instead of being
part of the first argument and then expects a comma (,) and the second
string argument

How I can make the parser take the 2nd quote as part of the first string
argument if there is a quote in the 1st argument
I know I could probably do this by replacing the double quotes with single
quotes but then I am assumming I will get the same problem with single
quotes been part of the literal string.

Your help is greatly appreciated. Thanks in advance

Regards David Furey
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top