 |
| 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
|
|
|
|

August 7th, 2013, 05:45 PM
|
|
Authorized User
|
|
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
|
|
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
|
|

August 7th, 2013, 06:28 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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:
|
|
|

August 8th, 2013, 03:26 AM
|
|
Authorized User
|
|
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
|
|
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?
|
|

August 8th, 2013, 07:11 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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:
|
|
|

August 8th, 2013, 07:43 AM
|
|
Authorized User
|
|
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
|
|
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.
|
|

August 8th, 2013, 08:32 AM
|
|
Authorized User
|
|
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
|
|
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!
|
|

August 13th, 2013, 10:33 AM
|
|
Authorized User
|
|
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
|
|
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
|
|

August 13th, 2013, 10:59 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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:
|
|
|

August 13th, 2013, 11:26 AM
|
|
Authorized User
|
|
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
|
|
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
|
|

August 14th, 2013, 11:19 AM
|
|
Authorized User
|
|
Join Date: Aug 2013
Posts: 30
Thanks: 9
Thanked 0 Times in 0 Posts
|
|
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
|
|
 |