By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
428,583 Members | 617 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 428,583 IT Pros & Developers. It's quick & easy.

[Newbie] Output something using XSLT even if an element is missing in some documents?

P: n/a
Hi All,

I am some information from INSPEC database records in XML to build a
relational database of my own. I am currently trying to extract information
by doing an XSLT transform of the XML files into a tab-separated text file
that I want to import into the database. I have run into the following
problem: in some documents there are missing elements, for instance the
volume and issue number of an article is not there (i.e. it is defined in
the DTD, but the element that contains these values happen not to be
included in some documents). This causes a problem because it messes up my
columns as all the rest of the elements I am extracting move left and thus
are placed in wrong columns.

My question is: is there some way in XSLT output a value like "empty" or
"N/A" when some elements are missing?

I use Xalan to do the transformations, and Altova XML spy / Stylevison to
create the XLSTs. Please find a excerpt from my XLST file below; it is the
"vol", "ino" and "voliss" elements that are sometimes empty.

Thank you for any help!

- John

<xsl:for-each select="bibliog">
<xsl:for-each select="jrefg">
<xsl:for-each select="jrog">
<xsl:for-each select="jt">
<xsl:apply-templates/>
</xsl:for-each>
<xsl:text</xsl:text>
<xsl:for-each select="ajt">
<xsl:apply-templates/>
</xsl:for-each>
<xsl:text</xsl:text>
<xsl:for-each select="vid">
<xsl:for-each select="vol">
<xsl:apply-templates/>
</xsl:for-each>
<xsl:text</xsl:text>
<xsl:for-each select="ino">
<xsl:apply-templates/>
</xsl:for-each>
<xsl:text</xsl:text>
<xsl:for-each select="voliss">
<xsl:apply-templates/>
</xsl:for-each>
</xsl:for-each>
<xsl:text</xsl:text>
<xsl:for-each select="pgn">
<xsl:apply-templates/>
</xsl:for-each>
<xsl:text</xsl:text>
</xsl:for-each>
</xsl:for-each>
<xsl:text</xsl:text>
<xsl:for-each select="norefs">
<xsl:apply-templates/>
</xsl:for-each>
<xsl:text</xsl:text>
<xsl:for-each select="ti">
<xsl:apply-templates/>
</xsl:for-each>
<xsl:text</xsl:text>
<xsl:for-each select="abs">
<xsl:apply-templates/>
</xsl:for-each>
<xsl:text</xsl:text>
</xsl:for-each>


Sep 27 '08 #1
Share this Question
Share on Google+
6 Replies


P: n/a
John Larson wrote:
Hi All,

I am some information from INSPEC database records in XML to build a
relational database of my own. I am currently trying to extract information
by doing an XSLT transform of the XML files into a tab-separated text file
that I want to import into the database. I have run into the following
problem: in some documents there are missing elements, for instance the
volume and issue number of an article is not there (i.e. it is defined in
the DTD, but the element that contains these values happen not to be
included in some documents). This causes a problem because it messes up my
columns as all the rest of the elements I am extracting move left and thus
are placed in wrong columns.

My question is: is there some way in XSLT output a value like "empty" or
"N/A" when some elements are missing?
For your inspiration: here an example stylesheet which is properly transforming XML documents into tab-separated text files: http://tinyurl.com/3zf2bo

Hope this helps, Hermann
Sep 27 '08 #2

P: n/a
"Hermann Peifer" <pe****@gmx.netwrote in message
news:48**************@gmx.net...
For your inspiration: here an example stylesheet which is properly
transforming XML documents into tab-separated text files:
http://tinyurl.com/3zf2bo

Hope this helps, Hermann
Thanks Herman! I have now tried to construct a new XSLT based on your
example (see the full text at the end). I think I have got it almost right,
but when I try to run it in Xalan against my XML files I get the following
exception:

file:///data/disk21/tab-output.xslt; Line #71; Column #79; XSLT Error
(javax.xml.transform.TransformerConfigurationExcep tion):
javax.xml.transform.TransformerException: org.xml.sax.SAXParseException:
Open quote is expected for attribute "select" associated with an element
type "xsl:value-of".
Exception in thread "main" java.lang.RuntimeException:
javax.xml.transform.TransformerException: org.xml.sax.SAXParseException:
Open quote is expected for attribute "select" associated with an element
type "xsl:value-of".
at org.apache.xalan.xslt.Process.doExit(Process.java: 1153)
at org.apache.xalan.xslt.Process.main(Process.java:11 26)

As far as I can see it does not like my qoutes, but they are exactly like
yours. I run Xalan on a Linux server. The XSLT file is saved in Unix file
format and ANSI encoding using TextPad, and then copied as binary to the
server.

Any ideas how to fix this?

Thanks again - John

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<!-- Stylesheet inspired by one by Hermann Peifer, EEA, March 2008 -->

<!-- Variable definition for tab delimited output -->
<xsl:variable name="newline" select="'&#x0A;'"/>
<xsl:variable name="tab" select="'&#x09;'"/>
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/">

<!-- Write out field names -->
<xsl:text>accn</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>abgn</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>newrt</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>rtname</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>jt</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>ajt</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>vol</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>ino</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>voliss</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>yr</xsl:text <xsl:value-of select="$newline"/>

<xsl:apply-templates select="inspec/article"/>

</xsl:template>

<!-- Loop through each field -->
<xsl:template match="article">
<xsl:value-of select="inspec/article/contg/accn"/ <xsl:value-of
select="$tab"/>
<xsl:value-of select="inspec/article/contg/abng"/ <xsl:value-of
select="$tab"/>
<xsl:value-of select="inspec/article/contg/rtypg/newrt"/ <xsl:value-of
select="$tab"/>
<xsl:value-of select="inspec/article/contg/rtypg/rtng/rtname"/>
<xsl:value-of select="$tab"/>
<xsl:value-of select="inspec/article/bibliog/jrefg/jrog/jt"/>
<xsl:value-of select="$tab"/>
<xsl:value-of select="inspec/article/bibliog/jrefg/jrog/ajt"/>
<xsl:value-of select="$tab"/>
<xsl:value-of select="inspec/article/bibliog/jrefg/jrog/vid/vol"/>
<xsl:value-of select="$tab"/>
<xsl:value-of select="inspec/article/bibliog/jrefg/jrog/vid/ino"/>
<xsl:value-of select="$tab"/>
<xsl:value-of select="inspec/article/bibliog/jrefg/jrog/vid/voliss"/>
<xsl:value-of select="$tab"/>
<xsl:value-of select="inspec/article/contg/crt/yr"/ <xsl:value-of
select=$newline"/>
</xsl:template>

</xsl:stylesheet>
Sep 27 '08 #3

P: n/a
I wrote:
As far as I can see it does not like my qoutes, but they are exactly like
yours. I run Xalan on a Linux server. The XSLT file is saved in Unix file
format and ANSI encoding using TextPad, and then copied as binary to the
server.

Any ideas how to fix this?
My apologies - there was a quote missing right at the end by newline. After
fixing this the tranformation now runs. Sadly the output only contains the
field name and a lot of tabs - none of the content is printed out (and there
is content in some elements that should be there).

The root element of my XML files is "inspec" and each file contains an
number of articles, which is next level down in the tree. The data I want to
extract is in child elements under article. An example XPATH is
"inspec/article/bibliog/jrefg/jrog/vid/vol". Am I somehow pointing
incorrectly or not calling the select correctly or ?

Thanks - John

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<!-- Stylesheet inspired by one by Hermann Peifer, EEA, March 2008 -->

<!-- Variable definition for tab delimited output -->
<xsl:variable name="newline" select="'&#x0A;'"/>
<xsl:variable name="tab" select="'&#x09;'"/>
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/">

<!-- Write out field names -->
<xsl:text>accn</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>abgn</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>newrt</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>rtname</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>jt</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>ajt</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>vol</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>ino</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>voliss</xsl:text <xsl:value-of select="$tab"/>
<xsl:text>yr</xsl:text <xsl:value-of select="$newline"/>

<xsl:apply-templates select="inspec/article"/>

</xsl:template>

<!-- Loop through each field -->
<xsl:template match="article">
<xsl:value-of select="inspec/article/contg/accn"/<xsl:value-of
select="$tab"/>
<xsl:value-of select="inspec/article/contg/abng"/<xsl:value-of
select="$tab"/>
<xsl:value-of select="inspec/article/contg/rtypg/newrt"/<xsl:value-of
select="$tab"/>
<xsl:value-of select="inspec/article/contg/rtypg/rtng/rtname"/>
<xsl:value-of select="$tab"/>
<xsl:value-of select="inspec/article/bibliog/jrefg/jrog/jt"/<xsl:value-of
select="$tab"/>
<xsl:value-of select="inspec/article/bibliog/jrefg/jrog/ajt"/>
<xsl:value-of select="$tab"/>
<xsl:value-of select="inspec/article/bibliog/jrefg/jrog/vid/vol"/>
<xsl:value-of select="$tab"/>
<xsl:value-of select="inspec/article/bibliog/jrefg/jrog/vid/ino"/>
<xsl:value-of select="$tab"/>
<xsl:value-of select="inspec/article/bibliog/jrefg/jrog/vid/voliss"/>
<xsl:value-of select="$tab"/>
<xsl:value-of select="inspec/article/contg/crt/yr"/<xsl:value-of
select="$newline"/>
</xsl:template>

</xsl:stylesheet>

Sep 27 '08 #4

P: n/a

"John Larson" wrote:
My apologies - there was a quote missing right at the end by newline.
After fixing this the tranformation now runs. Sadly the output only
contains the field name and a lot of tabs - none of the content is printed
out (and there is content in some elements that should be there).

The root element of my XML files is "inspec" and each file contains an
number of articles, which is next level down in the tree. The data I want
to extract is in child elements under article. An example XPATH is
"inspec/article/bibliog/jrefg/jrog/vid/vol". Am I somehow pointing
incorrectly or not calling the select correctly or ?

Thanks - John
After a lot of trial and error I figured out that I needed to shorten my
XPATHs in the value of select statements (e.g. from <xsl:value-of
select="inspec/article/contg/accn"/to <xsl:value-of
select="contg/accn"/>). It now works beautifully - thanks to Hermann for
pointing to this solution.

Best

- John
Sep 27 '08 #5

P: n/a

"John Larson" wrote:
My apologies - there was a quote missing right at the end by newline.
After fixing this the tranformation now runs. Sadly the output only
contains the field name and a lot of tabs - none of the content is printed
out (and there is content in some elements that should be there).

The root element of my XML files is "inspec" and each file contains an
number of articles, which is next level down in the tree. The data I want
to extract is in child elements under article. An example XPATH is
"inspec/article/bibliog/jrefg/jrog/vid/vol". Am I somehow pointing
incorrectly or not calling the select correctly or ?

Thanks - John
After a lot of trial and error I figured out that I needed to shorten my
XPATHs in the value of select statements (e.g. from <xsl:value-of
select="inspec/article/contg/accn"/to <xsl:value-of
select="contg/accn"/>). It now works beautifully - thanks to Hermann for
pointing to this solution.

Best

- John

Sep 27 '08 #6

P: n/a
John Larson wrote:
"John Larson" wrote:
>My apologies - there was a quote missing right at the end by newline.
After fixing this the tranformation now runs. Sadly the output only
contains the field name and a lot of tabs - none of the content is printed
out (and there is content in some elements that should be there).

The root element of my XML files is "inspec" and each file contains an
number of articles, which is next level down in the tree. The data I want
to extract is in child elements under article. An example XPATH is
"inspec/article/bibliog/jrefg/jrog/vid/vol". Am I somehow pointing
incorrectly or not calling the select correctly or ?

Thanks - John

After a lot of trial and error I figured out that I needed to shorten my
XPATHs in the value of select statements (e.g. from <xsl:value-of
select="inspec/article/contg/accn"/to <xsl:value-of
select="contg/accn"/>). It now works beautifully - thanks to Hermann for
pointing to this solution.

Best

- John
Good to hear that you got it right.

You could add a leading slash to your select attribute:
<xsl:apply-templates select="/inspec/article"/>

Then, the XSLT processor will only search for inspec/article elements, which are immediately under the root element, and not somewhere in the middle of the XML structure (which might not occur in your XML document, but being as specific as possible is always a good idea, as it also saves processing time).

I assume that each article has max. 1 accn, abgn, etc. elements. If not: you will only get the value of the first one.

Hermann
Sep 28 '08 #7

This discussion thread is closed

Replies have been disabled for this discussion.