Solved

how to get the content of a section from a node in xml to xml conversion using xslt 1.0

Posted on 2011-09-12
6
337 Views
Last Modified: 2013-11-18
My xml is attached. I am trying to acheive this


                                    <misbn>
                                          9780470697900; 9780470512661; 9780470059081; 9780470697870
                                    </misbn>
the rules are

Content of <dc:identifier_isbn> AND
Content of the last section after the final / of the <dc:identifier_dbid> which contains text "dx.doi.org". If more than one of these use first only.
Separate entries with semicolon and a space

Example:
<dc:identifier_isbn>9780470697900</dc:identifier_isbn>
<dc:identifier_isbn>9780470512661</dc:identifier_isbn>
<dc:identifier_isbn>9780470059081</dc:identifier_isbn>
<dc:identifier>http://dx.doi.org/10.1002/9780470697870</dc:identifier>

"9780470697900; 9780470512661; 9780470059081; 9780470697870"
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <rdf:Description>
 <dc:identifier>http://www.myilibrary.com?id=234220</dc:identifier>
    <dc:identifier>http://www.netlibrary.com/urlapi.asp?action=summary&amp;v=1&amp;bookid=323900</dc:identifier>
    <dc:identifier>http://catdir.loc.gov/catdir/toc/ecip0719/2007022434.html</dc:identifier>
    <dc:identifier_isbn>9780470697900</dc:identifier_isbn>
    <dc:identifier_isbn>9780470512661 </dc:identifier_isbn>
    <dc:identifier_isbn>9780470059081 </dc:identifier_isbn>
    <dc:identifier_isbn></dc:identifier_isbn>
    <dc:identifier_isbn></dc:identifier_isbn>
    <dc:identifier_isbn></dc:identifier_isbn>
    <dc:identifier_isbn></dc:identifier_isbn>
    <dc:identifier_dbid>http://site.ebrary.com/id/10297565</dc:identifier_dbid>
    <dc:identifier_dbid>http://dx.doi.org/10.1002/9780470697870</dc:identifier_dbid>
    <dc:identifier_dbid>http://www.myilibrary.com?id=234220</dc:identifier_dbid>
    <dc:identifier_dbid>http://www.netlibrary.com/urlapi.asp?action=summary&amp;v=1&amp;bookid=323900</dc:identifier_dbid>
    <dc:identifier_dbid>http://catdir.loc.gov/catdir/toc/ecip0719/2007022434.html</dc:identifier_dbid>
</rdf:Description>
</rdf:RDF>

Open in new window

0
Comment
Question by:mmalik15
  • 4
6 Comments
 
LVL 18

Accepted Solution

by:
zc2 earned 250 total points
ID: 36523049
Please, give a try to the following script:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">

	<xsl:key name="ik" match="dc:identifier_isbn|dc:identifier_dbid" use="."/>

	<xsl:template match="rdf:Description">

		<xsl:for-each 
select="dc:identifier_isbn[string-length(normalize-space(.)) and generate-id(.) = generate-id(key('ik',.))]|dc:identifier_dbid[contains(.,'http://dx.doi.org') and generate-id(.) = generate-id(key('ik',.))]">
			<xsl:choose>
			   <xsl:when test="name() = 'dc:identifier_dbid'">
				   	<xsl:call-template name="after-slash">
				   		<xsl:with-param name="s" select="."/>
				   	</xsl:call-template>
			   </xsl:when>
			   <xsl:otherwise><xsl:value-of select="normalize-space(.)"/></xsl:otherwise>
			</xsl:choose>			
			<xsl:if test="position() != last()">; </xsl:if>
  		</xsl:for-each>
	</xsl:template>
	
	<xsl:template name="after-slash">
		<xsl:param name="s"/>
		<xsl:variable name="as" select="substring-after($s,'/')"/>
		<xsl:choose>
		   <xsl:when test="not(string-length($as))"><xsl:value-of select="$s"/></xsl:when>
		   <xsl:otherwise>
		   	<xsl:call-template name="after-slash">
		   		<xsl:with-param name="s" select="$as"/>
		   	</xsl:call-template>
		   
		   </xsl:otherwise>
		</xsl:choose>
	</xsl:template>	
	
</xsl:stylesheet>

Open in new window

0
 
LVL 60

Assisted Solution

by:Geert Bormans
Geert Bormans earned 250 total points
ID: 36523104
The tricky bit is getting the part after the last '/' for which you need recursion
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
    xmlns:dc="http://purl.org/dc/elements/1.1/"
     exclude-result-prefixes="rdf dc"
    version="1.0">
    <xsl:template name="get-file-part">
        <xsl:param name="str"/>
        <xsl:choose>
            <xsl:when test="contains($str, '/')">
                <xsl:call-template name="get-file-part">
                    <xsl:with-param name="str" select="substring-after($str, '/')"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$str"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    
    <xsl:template match="rdf:Description">
        <xsl:element name="misbn">
            <xsl:apply-templates select="dc:identifier_isbn[normalize-space(.)] | dc:identifier_dbid[contains(., 'dx.doi.org')][1]"/>
        </xsl:element>
    </xsl:template>
    
    <xsl:template match="dc:identifier_isbn">
        <xsl:if test="not(position() =  1)">
            <xsl:text>; </xsl:text>
        </xsl:if>
        <xsl:value-of select="."/>
    </xsl:template>

    <xsl:template match="dc:identifier_dbid">
        <xsl:if test="not(position() =  1)">
            <xsl:text>; </xsl:text>
        </xsl:if>
        <xsl:call-template name="get-file-part">
            <xsl:with-param name="str" select="."/>
        </xsl:call-template>
    </xsl:template>
</xsl:stylesheet>

Open in new window

0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 36523196
I see that zc2 posted as well, solutions are almost equivalent, but zc2's solution provides unique nodes,
something you did not ask for, but I assume can be handy

other notable difference

- the choose construct in zc2's code is replaced by an apply templates, so the sector happens in the template matches.
Letting the template matching mechanism deal with choices is considered an XSLT best practice
- that also solves the issue you could run into with this <xsl:when test="name() = 'dc:identifier_dbid'">
if you prefer to keep the choose construct this would be better <xsl:when test="self::dc:identifier_dbid"> for various reasons
0
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 

Author Closing Comment

by:mmalik15
ID: 36523431
Excellent guys
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 36523443
Here is an alternative for my stylesheet, still having the matching doing its work after apply-templates,
but returning unique nodes only
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
    xmlns:dc="http://purl.org/dc/elements/1.1/"
     exclude-result-prefixes="rdf dc"
    version="1.0">
    
    <xsl:key name="unique" match="dc:identifier_isbn[normalize-space(.)] | dc:identifier_dbid[contains(., 'dx.doi.org')][not(preceding-sibling::dc:identifier_dbid[contains(., 'dx.doi.org')])]" use="normalize-space(.)"/>
    
    <xsl:template name="get-file-part">
        <xsl:param name="str"/>
        <xsl:choose>
            <xsl:when test="contains($str, '/')">
                <xsl:call-template name="get-file-part">
                    <xsl:with-param name="str" select="substring-after($str, '/')"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="normalize-space($str)"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    
    <xsl:template match="rdf:Description">
        <xsl:element name="misbn">
            <xsl:apply-templates select="*[generate-id() = generate-id(key('unique', normalize-space(.))[1])]"/>
        </xsl:element>
    </xsl:template>
    
    <xsl:template match="dc:identifier_isbn">
        <xsl:if test="not(position() =  1)">
            <xsl:text>; </xsl:text>
        </xsl:if>
        <xsl:value-of select="normalize-space(.)"/>
    </xsl:template>

    <xsl:template match="dc:identifier_dbid">
        <xsl:if test="not(position() =  1)">
            <xsl:text>; </xsl:text>
        </xsl:if>
        <xsl:call-template name="get-file-part">
            <xsl:with-param name="str" select="."/>
        </xsl:call-template>
    </xsl:template>
</xsl:stylesheet>

Open in new window

0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 36523445
welcome
0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

One of the biggest challenges facing freelancers is balancing multiple projects and deadlines. Organizational skills and time management are key to keeping up with projects and staying on track. Luckily, we’ve curated seven tools to help you focus o…
Gift cards are not a new concept - it's been around for a very long time.  Undoubtedly, over the past you have received such a card or purchased one for a friend or relative.  Are you aware that you've been feeding the machine?  If not, read on :)
The viewer will learn how to count occurrences of each item in an array.
Saved searches can save you time by quickly referencing commonly searched terms on any topic. Whether you are looking for questions you can answer or hoping to learn about a specific issue, a saved search can help you get the most out of your time o…

808 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question