Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old August 7th, 2013, 05:45 PM
Authorized User
 
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
Default multiple substitutions

Dear all,

I am a beginner, and here is my problem:

I want to transform this plain text

[H]erc(uli) Aug(usto) / Ael(ius) Civilis / mil(es)
leg(ionis) VII Cl(audiae) / [|(centuria)] Aufidini
V[ic]/toris p(rimi) p(ili) / h(oc) s(ignum) f(ecit)

into marked up xml. I have tried with this XSLT 2.0

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml"/>
<xsl:template match="/">
<ab>
<xsl:analyze-string select="/" regex="/">
<xsl:matching-substring>
<lb/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
<xsl:analyze-string select="/" regex="\[(.*?)\]">
<xsl:matching-substring>
<supplied reason="lost">
<xsl:value-of select="regex-group(1)"/>
</supplied>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
<xsl:analyze-string select="/" regex="\((.*?)\)">
<xsl:matching-substring>
<ex>
<xsl:value-of select="regex-group(1)"/>
</ex>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>

</ab>
</xsl:template>

</xsl:stylesheet>


but I get results three times...

<ab>
[H]erc(uli) Aug(usto) <lb/> Ael(ius) Civilis <lb/> mil(es)
leg(ionis) VII Cl(audiae) <lb/> [|(centuria)] Aufidini
V[ic]<lb/>toris p(rimi) p(ili) <lb/> h(oc) s(ignum) f(ecit)

<supplied reason="lost">H</supplied>erc(uli) Aug(usto) / Ael(ius) Civilis / mil(es)
leg(ionis) VII Cl(audiae) / <supplied reason="lost">|(centuria)</supplied> Aufidini
V<supplied reason="lost">ic</supplied>/toris p(rimi) p(ili) / h(oc) s(ignum) f(ecit)

[H]erc<ex>uli</ex> Aug<ex>usto</ex> / Ael<ex>ius</ex> Civilis / mil<ex>es</ex>
leg<ex>ionis</ex> VII Cl<ex>audiae</ex> / [|<ex>centuria</ex>] Aufidini
V[ic]/toris p<ex>rimi</ex> p<ex>ili</ex> / h<ex>oc</ex> s<ex>ignum</ex> f<ex>ecit</ex>
</ab>

why? how can I get all substitutions in tha same text?

Thank you very much
sincerely
Pietro
 
Old August 7th, 2013, 06:28 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

In XSLT if you write a sequence constructor containing three instructions then the result is the concatenation of the output of the three instructions. The three instructions all operate on the same input; you are imagining that the second takes the result of the first as its input, and the third one takes the result of the second. If that's what you want to achieve then you need to capture the results of one phase in a variable:

Code:
<xsl:variable name="a">
  <xsl:analyze-string select="." .../>
</xsl:variable>
<xsl:variable name="b">
  <xsl:analyze-string select="$a" .../>
</xsl:variable>
<xsl:analyze-string select="$b" .../>
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
The Following User Says Thank You to mhkay For This Useful Post:
pietromaria.liuzzo (August 13th, 2013)
 
Old August 8th, 2013, 03:26 AM
Authorized User
 
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
Default

Thank you very much!

I have now tried to apply your suggestion, like this:

Code:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml"/>
    <xsl:template match="/">
        <ab>          
    <xsl:variable name="linebreak">
                <xsl:analyze-string select="." regex="/"> 
                    <xsl:matching-substring>
                        <lb/>
                    </xsl:matching-substring>
                    <xsl:non-matching-substring>
                        <xsl:value-of select="."/>
                    </xsl:non-matching-substring>
                </xsl:analyze-string>
            </xsl:variable>
            <xsl:variable name="supplied">
                <xsl:analyze-string select="$linebreak" regex="\[(.*?)\]">
                    <xsl:matching-substring>
                        <supplied reason="lost">
                            <xsl:value-of select="regex-group(1)"/>
                        </supplied>
                    </xsl:matching-substring>
                    <xsl:non-matching-substring>
                        <xsl:value-of select="."/>
                    </xsl:non-matching-substring>
                </xsl:analyze-string>
            </xsl:variable>
            
                <xsl:analyze-string select="$supplied" regex="\((.*?)\)">
                    <xsl:matching-substring>
                        <ex>
                            <xsl:value-of select="regex-group(1)"/>
                        </ex>
                    </xsl:matching-substring>
                    <xsl:non-matching-substring>
                        <xsl:value-of select="."/>
                    </xsl:non-matching-substring>
                </xsl:analyze-string>

                
        </ab>
    </xsl:template>
    
</xsl:stylesheet>
and the result is much better, although I must have done something wrong again and I only get the last instruction to operate,
Code:
<?xml version="1.0" encoding="UTF-8"?><ab>
Herc<ex>uli</ex> Aug<ex>usto</ex>  Ael<ex>ius</ex> Civilis  mil<ex>es</ex>
leg<ex>ionis</ex> VII Cl<ex>audiae</ex>  |<ex>centuria</ex> Aufidini
Victoris p<ex>rimi</ex> p<ex>ili</ex>  h<ex>oc</ex> s<ex>ignum</ex> f<ex>ecit</ex>
</ab>
Could you please help me again?
 
Old August 8th, 2013, 07:11 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Your next problem is that your first phase of processing is inserting elements into the string, but the second phase of processing using analyze-string flattens the input to a string, so these elements disappear. Ditto the second phase also inserts elements.

Your example input shows round brackets nested inside square brackets but I don't know if that's the only form of nesting that's possible. If it is, then doing the analyze-string for round brackets inside the xsl:matching-substring section of the phase where you match square brackets might be the answer. Generally you probably want one phase of processing to build a node-tree, and then you want to use apply-templates to process this node-tree recursively, copying the elements and doing regex processing on the text nodes.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
The Following User Says Thank You to mhkay For This Useful Post:
pietromaria.liuzzo (August 13th, 2013)
 
Old August 8th, 2013, 07:43 AM
Authorized User
 
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
Default

Thank you very much again!
yes, basically all I want to do is to replace those braces with xml elements. can I avoid the flattening to a string and have it perform all instructions on that same text?

I have tried to use apply-templates but without success. Where should I put it? I have tried like this

Code:
<ab>          
                <xsl:analyze-string select="." regex="/"> 
                    <xsl:matching-substring>
                        <lb/>
                    </xsl:matching-substring>
                    <xsl:non-matching-substring>
                        <xsl:value-of select="."/>
                    </xsl:non-matching-substring>
                </xsl:analyze-string> 
            <xsl:apply-templates/>
        </ab>
and then I have pointed the other instructions to my ab

There is no overlap between the three substitutions, but there must be something obvious which I am missing, I apologize about this and thank you very much for any further help.
 
Old August 8th, 2013, 08:32 AM
Authorized User
 
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
Default

I have now tried like this

Code:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml"/>
    <xsl:template match="/">
        <ab>          
                <xsl:analyze-string select="." regex="/"> 
                    <xsl:matching-substring>
                        <lb/>
                    </xsl:matching-substring>
                    <xsl:non-matching-substring>
                        <xsl:analyze-string select="." regex="\[(.*?)\]">
                            <xsl:matching-substring>
                                <supplied reason="lost">
                                    <xsl:value-of select="regex-group(1)"/>
                                </supplied>
                            </xsl:matching-substring>
                            <xsl:non-matching-substring>
                                <xsl:analyze-string select="." regex="\((.*?)\)">
                                    <xsl:matching-substring>
                                        <ex>
                                            <xsl:value-of select=" regex-group(1)"/>
                                        </ex>
                                    </xsl:matching-substring>
                                    <xsl:non-matching-substring>
                                        <xsl:value-of select="."/>
                                    </xsl:non-matching-substring>
                                </xsl:analyze-string>
                            </xsl:non-matching-substring>
                        </xsl:analyze-string>
                    </xsl:non-matching-substring>
                </xsl:analyze-string>
                        </ab>
    </xsl:template>
    
</xsl:stylesheet>
result

Code:
<ab>

<supplied reason="lost">H</supplied>erc<ex>uli</ex> Aug<ex>usto</ex> <lb/> Ael<ex>ius</ex> Civilis <lb/> mil<ex>es</ex>
leg<ex>ionis</ex> VII Cl<ex>audiae</ex> <lb/> <supplied reason="lost">|(centuria)</supplied> Aufidini
V<supplied reason="lost">ic</supplied><lb/>toris p<ex>rimi</ex> p<ex>ili</ex> <lb/> h<ex>oc</ex> s<ex>ignum</ex> f<ex>ecit</ex>

</ab>
probably I now understood what you meant. Thank you!
 
Old August 13th, 2013, 10:33 AM
Authorized User
 
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
Default

Dear all, especially dear mhkay, I have gone down that road and managed to do quite a lot of upconversion indeed.

I have now this string

[inos? gin? pin?]

and I am using this instruction:

Code:
<xsl:analyze-string select="." regex="\[(.*?)\?\]">
<xsl:matching-substring>
<supplied reason="lost" cert="low">
<xsl:value-of select="regex-group(1)"/>
</supplied>
</xsl:matching-substring> ...
I then get this result

Code:
<supplied reason="lost" cert="low">inos? gin? pin </supplied>
I would like to remove the remaining "?" and I have tried like this:

Code:
<xsl:analyze-string select="." regex="\[(.*?)\?\]">
<xsl:matching-substring>
<supplied reason="lost" cert="low">
<xsl:value-of select="regex-group(1)"/>
<xsl:value-of select="translate('?', '?', ' ')"/>
</supplied>
</xsl:matching-substring> ...
with no effect...

can you please give me some advise?

Thank you very much

Pietro
 
Old August 13th, 2013, 10:59 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

The expression translate('?', '?', ' ') produces a single space, it doesn't have any input apart from literal strings.

You are still writing your code as if one instruction somehow takes its input from the result of the previous instruction. That's simply not how it works. You need to use functional composition:

Code:
translate(regex-group(1), '?', '')
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
The Following User Says Thank You to mhkay For This Useful Post:
pietromaria.liuzzo (August 13th, 2013)
 
Old August 13th, 2013, 11:26 AM
Authorized User
 
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
Default

Thank you very much!

I understand that I do have problems to understand how it works. I am reading the book, following advice, doing plenty of exercise, but there is still something I do not get at all as it appears. I have started a couple of weeks ago, so I hope that I will understand at some point.

Thanks again for your help.

Sincerely
Pietro
 
Old August 14th, 2013, 11:19 AM
Authorized User
 
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
Default

I have tried to apply a suggestion below about variables and used the xsl:call-template as explained in the book, and I have done this:

Code:
<xsl:variable name="div">
        <xsl:for-each select="."><xsl:call-template name="textparts"/></xsl:for-each>
    </xsl:variable>
    <xsl:variable name="brackets">
        <xsl:for-each select="$div//text()"><xsl:call-template name="breakbrackets"/></xsl:for-each>
    </xsl:variable>
    <xsl:variable name="substitutions">
        <xsl:for-each select="$brackets"><xsl:call-template name="upconversion"/></xsl:for-each>
    </xsl:variable>
the first template textparts uses analyze-string to find a pattern and looks like this:

Code:
 <xsl:template match="." name="textparts">
          <text>
              <xsl:analyze-string select="." regex="(.*)//(.*)" flags="s">
                <xsl:matching-substring>
                    <div type="textpart" subtype="text">
                        <ab>
                            <xsl:value-of select="regex-group(1)"/>
                        </ab>
                    </div>
                    <div type="textpart" subtype="text">
                        <ab>
                            <xsl:value-of select="regex-group(2)"/>
                        </ab>
                    </div>
                </xsl:matching-substring>
            </xsl:analyze-string>
          </text>
        
    </xsl:template>
the following ones instead are used, the first to substitute some braces so that the third template can do all the substitutions.

when I use this the element nodes I asked for in the first template are lost, but I do get the third to work on the results of the second very nicely. How can I preserve them and apply the templates only to the text into the nodes I have created in the first stage?

I have tried to use variables into apply-templates into my first template (above, in the <ab/>) and also to put them changing the variables structure after analyze-string. but I get only the result of the main template in this case.

Thank you very much again for all your help





Similar Threads
Thread Thread Starter Forum Replies Last Post
Help with parsing XML file (substitutions) yanzickp XSLT 1 July 25th, 2007 04:32 PM
Importing Multiple files in Multiple tables Versi Suomi Access 6 June 1st, 2005 08:47 AM
Multiple ADO multiple user login Oracle9i jhay0721 Pro VB Databases 1 April 4th, 2005 11:23 AM
Date time substitutions markvivian VS.NET 2002/2003 2 October 14th, 2004 12:11 AM
Updating multiple Rows from multiple fields in ASP vdm_nana SQL Server ASP 0 April 1st, 2004 04:26 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.