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

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Larson

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

    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>




  • Hermann Peifer

    #2
    Re: [Newbie] Output something using XSLT even if an element is missingin some documents?

    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

    Comment

    • John Larson

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

      "Hermann Peifer" <peifer@gmx.net wrote in message
      news:48DE7596.6 070203@gmx.net. ..
      For your inspiration: here an example stylesheet which is properly
      transforming XML documents into tab-separated text files:

      >
      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.tran sform.Transform erConfiguration Exception):
      javax.xml.trans form.Transforme rException: org.xml.sax.SAX ParseException:
      Open quote is expected for attribute "select" associated with an element
      type "xsl:value-of".
      Exception in thread "main" java.lang.Runti meException:
      javax.xml.trans form.Transforme rException: org.xml.sax.SAX ParseException:
      Open quote is expected for attribute "select" associated with an element
      type "xsl:value-of".
      at org.apache.xala n.xslt.Process. doExit(Process. java:1153)
      at org.apache.xala n.xslt.Process. main(Process.ja va:1126)

      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:styleshe et 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>acc n</xsl:text <xsl:value-of select="$tab"/>
      <xsl:text>abg n</xsl:text <xsl:value-of select="$tab"/>
      <xsl:text>newrt </xsl:text <xsl:value-of select="$tab"/>
      <xsl:text>rtnam e</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>volis s</xsl:text <xsl:value-of select="$tab"/>
      <xsl:text>yr</xsl:text <xsl:value-of select="$newlin e"/>

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


      Comment

      • John Larson

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

        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:styleshe et 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>acc n</xsl:text <xsl:value-of select="$tab"/>
        <xsl:text>abg n</xsl:text <xsl:value-of select="$tab"/>
        <xsl:text>newrt </xsl:text <xsl:value-of select="$tab"/>
        <xsl:text>rtnam e</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>volis s</xsl:text <xsl:value-of select="$tab"/>
        <xsl:text>yr</xsl:text <xsl:value-of select="$newlin e"/>

        <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="$newlin e"/>
        </xsl:template>

        </xsl:stylesheet>



        Comment

        • John Larson

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


          "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


          Comment

          • John Larson

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


            "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



            Comment

            • Hermann Peifer

              #7
              Re: [Newbie] Output something using XSLT even if an element is missingin some documents?

              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

              Comment

              Working...