|
Subject: Re: [xsl] constructing an element with an element's content based on the content of sibling element From: Syd Bauman <Syd_Bauman@xxxxxxxxx> Date: Mon, 11 Jun 2012 03:05:46 -0400 |
You're welcome.
I'm beginning to suspect that, like many folks who come to XSLT from
procedural languages like Perl or C, you are using mostly "pull"
processing (get X, put it here; get Y, put it next ...) rather than
mostly "push" processing (whenever you hit an X, do this; whenever
you hit a Y, do that).
The code I sent presumed that your XSLT was busy processing the
*parent* of the <productidentifier> element (e.g. a <containeditem>,
<notforsale>, <product>, <relatedproduct>, or <set>) when you wanted
the ISBN spit out as a <controlfield>. If you're going to use
<xsl:for-each select="productidentifier">
<xsl:call-template name="isbn"/>
</xsl:for-each>
then in the "isbn" template you're calling, the context node will be
the <productidentifier>. Thus to test for the existence of a <b221>
child element with the value '15', you test any one of the following,
which are equivalent
self::productidentifier/child::b221 = '15'
self::productidentifier/b221 = '15'
./child::b221 = '15'
./b221 = '15'
b221 = '15'
So in the code you just posted,
> <xsl:template name="isbn" match="productidentifier">
> <xsl:choose>
> <xsl:when test="productidentifier/b221 = '15'">
> <xsl:apply-templates select="productidentifier[b221='15']"/>
The template is being fired with a <productidentifier> as the current
node. So the test "productidentifier/b221" is asking to look at each
<b221> child of the <productidentifier> child of the currently being
processed <productidentifier>. Since there are no <productidentifier>
elements as children of the current <productidentifier>, the test can
never be true.
So you might try something like
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:marc="http://www.loc.gov/MARC21/slim" version="2.0">
<xsl:template match="/">
<marc:pretend-wrapper-to-hold-multiple-records>
<xsl:apply-templates select="wrapper/product"/>
</marc:pretend-wrapper-to-hold-multiple-records>
</xsl:template>
<xsl:template match="product">
<marc:record>
<xsl:for-each select="productidentifier">
<xsl:call-template name="isbn"/>
</xsl:for-each>
</marc:record>
</xsl:template>
<xsl:template name="isbn" match="productidentifier">
<xsl:choose>
<!-- first take care of "I am ISBN 13" case -->
<xsl:when test="child::b221 = '15'">
<controlfield tag="001">
<xsl:text>ISBN13 = </xsl:text>
<xsl:value-of select="b244"/>
</controlfield>
</xsl:when>
<!-- then ignore case where I have a sibling that is ISBN 13 -->
<xsl:when test="parent::*/child::productidentifier/child::b221 = '15'"/>
<!-- no sibling ISBN 13, so use ISBN 10, if that's what I am -->
<xsl:when test="child::b221 = '02'">
<controlfield tag="001">
<xsl:text>ISBN10 = </xsl:text>
<xsl:value-of select="b244"/>
</controlfield>
</xsl:when>
<xsl:otherwise>
<xsl:message>Danger, Will Robinson! a 'productidentifier' that is confusing</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Although I personally prefer the previous version.
> Thanks very much for your reply, Syd.
>
> My apologies, I didn't search the XSL archive specifically, many of
> the results from my google search queries included the archive. I
> also poured over Kay's tomb for the functions not(), exists(),
> empty() (got really excited for a moment with element
> -available()).
>
> My stylesheet has nearly 1300 lines of code transforming ONIX for
> Books 2.1 into MARCXML. I'm using XSLT 2.0 (use tokenize() not
> available in 1.0); Stylus Studio Enterprise edition 2010.
>
> In fact, the scenario for the need of an alternate ISBN is small
> but the variability of publisher encoding warrants this test I
> think.
>
> In place of the stylesheet segment in my OP, I substituted a
> call-template based on your reply. The main template of my
> stylesheet matches the product element with ONIXMessage as the
> context and I use call-template for the construction of 1XX, 7XX
> and 245 MARC fields given the complexity of those fields with
> respect to name and title elements in ONIX as well as punctuation
> in the MARCXML fields.
>
> Hadn't thought to use call-template here but also hadn't considered
> the predicates you offered, so I tried this based on your
> suggestion but get no controlfields at all. Wan't sure about the
> context of the value-of select paths, so tried value-of
> select="following-sibling::b244", too.
>
> <marc:record>
> .
> .
> <xsl:for-each select="productidentifier">
> <xsl:call-template name="isbn"/>
> </xsl:for-each>
> .
> .
> </marc:record
>
> <xsl:template name="isbn" match="productidentifier">
> <xsl:choose>
> <xsl:when test="productidentifier/b221 = '15'">
> <xsl:apply-templates select="productidentifier[b221='15']"/>
> </xsl:when>
> <xsl:otherwise>
> <xsl:apply-templates select="productidentifier[b221='02']"/>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:template>
>
> <xsl:template match="productidentifier[b221 eq '02']">
> <controlfield tag="001">
> <xsl:text>xyz</xsl:text>
> <xsl:value-of select="b244"/>
> </controlfield>
> </xsl:template>
>
> <xsl:template match="productidentifier[b221 eq '15']">
> <controlfield tag="001">
> <xsl:text>xyz</xsl:text>
> <xsl:value-of select="b244"/>
> </controlfield>
> </xsl:template>
>
> Most of my earlier efforts centered on the use of
> xsl:choose and xsl:otherwise. All failed so think I'm
> lacking a basic understanding of an important XSLT
> concept.
>
> Tried attaching a file with 3 records with the variation of presence
> of different product identifiers but my message was rejected even
> though in a text file.
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| Re: [xsl] constructing an element w, Dana Pearson | Thread | Re: [xsl] constructing an element w, Dana Pearson |
| Re: [xsl] constructing an element w, Dana Pearson | Date | Re: [xsl] Re: Keys, IDs lookup tabl, daniel whitney |
| Month |