XML
[ class tree: XML ] [ index: XML ] [ all elements ]

Source for file NITF.php

Documentation is available at NITF.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 2003-2004 TownNews.com                                 |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Patrick O'Lone <polone@townnews.com>                        |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // NITF.php,v 1.5 2005/03/18 14:38:42 polone Exp
  20.  
  21. require_once ('XML/Parser.php');
  22.  
  23. /**
  24. * Generic NITF Parser class
  25. *
  26. * This class provides basic NITF parsing. Many of the major elements of the NITF
  27. * standard are supported. This implementation is based off the NITF 3.1 DTD,
  28. * publicly available at the following URL:
  29. *
  30. * http://www.nitf.org/site/nitf-documentation/nitf-3-1.dtd
  31. *
  32. * Note that not all elements of this standard are not supported.
  33. *
  34. @author Patrick O'Lone <polone@townnews.com>
  35. @version 1.5
  36. @package XML
  37. */
  38. class XML_NITF extends XML_Parser
  39. {
  40.     /**
  41.     * @var array 
  42.     *  Document metadata. Container for metadata information about this
  43.     *  particular document.
  44.     * @see getDocData()
  45.     * @access private
  46.     */
  47.     var $m_kDocData = array ('key-list' => array ());
  48.  
  49.     /**
  50.     * @var array 
  51.     *  Information about specific instance of an item's publication. Contains
  52.     *  metadata about how the particular news object was used in a specific
  53.     *  instance.
  54.     * @see getPubData()
  55.     * @access private
  56.     */
  57.     var $m_kPubData = array ();
  58.  
  59.     /**
  60.     * @var array 
  61.     *  Information about the creative history of the document; also used as an
  62.     *  audit trail. Includes who made changes, when the changes were made, and
  63.     *  why. Each element of the array is a key-based array that corresponds to
  64.     *  the <revision-history> element.
  65.     * @see getRevision()
  66.     * @access private
  67.     */
  68.     var $m_akRevisions = array ();
  69.  
  70.     /**
  71.     * @var array 
  72.     *  The various headlines that were found in the document. The headlines are
  73.     *  keyed by the levels of HLX. The default hedline (if no level is found) is
  74.     *  HL1.
  75.     * @see getHedlines()
  76.     * @access private
  77.     */
  78.     var $m_kHedlines = array ('HL1' => null'HL2' => array ());
  79.  
  80.     /**
  81.     * @var string 
  82.     *  Story abstract summary or synopsis of the contents of the document.
  83.     * @access private
  84.     */
  85.     var $m_sAbstract = null;
  86.  
  87.     /**
  88.     * @var string 
  89.     *  Significant place mentioned in an article. Used to normalize locations.
  90.     *  The location in this variable is the place where the story's events will
  91.     *  or have unfolded.
  92.     * @access private
  93.     */
  94.     var $m_sLocation = null;
  95.  
  96.     /**
  97.     * @var string 
  98.     *  Information distributor. May or may not be the owner or creator.
  99.     * @access private
  100.     */
  101.     var $m_sDistributor = null;
  102.  
  103.     /**
  104.     * @var string 
  105.     *  The elements of the byline, including the author's name and title.
  106.     * @see getByline()
  107.     * @access private
  108.     */
  109.     var $m_kByline = array ('author' => null'title' => null);
  110.  
  111.     /**
  112.     * @var array 
  113.     *  An array of paragraphs extracted from the document
  114.     * @see getLede(), getContent()
  115.     * @access private
  116.     */
  117.     var $m_aContent = array ();
  118.  
  119.     /**
  120.     * @var array 
  121.     *  A list of media reference elements as found in the body section of the
  122.     *  document. Each element is an array itself with keyed properties related
  123.     *  to media element in question.
  124.     * @see getMedia()
  125.     * @access private
  126.     */
  127.     var $m_aMedia = array ();
  128.  
  129.     /**
  130.     * @var array 
  131.     *  A list of tags that were parsed (in order) denoting the current sequence
  132.     *  of tags that were parsed. This is array is used for parsing the document
  133.     *  elements in a particular order (if needed).
  134.     * @see StartHandler(), EndHandler(), cdataHandler()
  135.     * @access private
  136.     */
  137.     var $m_aParentTags = array ();
  138.  
  139.     /**
  140.     * @var string 
  141.     *  A byline at the end of a story. Example: Stuart Myles contributed to this
  142.     *  article.
  143.     * @see getTagline()
  144.     * @access private
  145.     */
  146.     var $m_sTagline = null;
  147.  
  148.     /**
  149.     * @var string 
  150.     *  Free-form bibliographic data. Used to elaborate on the source of
  151.     *  information.
  152.     * @see getBibliography()
  153.     * @access private
  154.     */
  155.     var $m_sBibliography = null;
  156.  
  157.     /**
  158.     * Access all or specific elements of the <docdata> block
  159.     *
  160.     * @return mixed 
  161.     *  All of the elements from the <docdata> block will be returned if a specific
  162.     *  property is not provided. If a specific property is requested and is found
  163.     *  in the docdata block, then that property will be returned. If the property
  164.     *  cannot be found, null is returned.
  165.     *
  166.     * @param string 
  167.     *  The property of the <docdata> block to return, the most common being:
  168.     *
  169.     *  "doc-id" - a unique identifier of this document (string)
  170.     *  "key-list" - a list of keywords provided with the document (array)
  171.     *  "copyright" - the copyright holder (string)
  172.     *  "series" - if the document is part of series (string)
  173.     *  "urgency" - a number between 1 (urgent) and 8 (not urgent) (integer)
  174.     *  "date.issue" - date the document was issued (UNIX timestamp)
  175.     *  "date.release" - date the document is publicly available (UNIX timestamp)
  176.     *  "date.expires" - date the document is no longer valid (UNIX timestamp)
  177.     *
  178.     * @see getDocDataElement()
  179.     * @access public
  180.     */
  181.     function getDocData($sProperty = null)
  182.     {
  183.         if (!empty ($sProperty)) {
  184.  
  185.             $sProperty strtolower($sProperty);
  186.             if (isset ($this->m_kDocData[$sProperty])) {
  187.  
  188.                 return $this->m_kDocData[$sProperty];
  189.  
  190.             }
  191.             return null;
  192.  
  193.         }
  194.         return $this->m_kDocData;
  195.     }
  196.  
  197.     /**
  198.     * Returns all elements or a specific element from the <pubdata> block
  199.     *
  200.     * @return mixed 
  201.     *  Returns string, numeric, or array values depending on the property being
  202.     *  accessed from the <pubdata> block.
  203.     *
  204.     * @access public
  205.     */
  206.     function getPubData($sProperty = null)
  207.     {
  208.         if (!empty ($sProperty)) {
  209.  
  210.             $sProperty strtolower($sProperty);
  211.             if (isset ($this->m_kPubData[$sProperty])) {
  212.  
  213.                 return $this->m_kPubData[$sProperty];
  214.  
  215.             }
  216.             return null;
  217.  
  218.         }
  219.  
  220.         return $this->m_kPubData;
  221.     }
  222.  
  223.     /**
  224.     * Get the revision history
  225.     *
  226.     * @return array 
  227.     *  An array containing key-value arrays. The properties of each array element
  228.     *  in this array are:
  229.     *
  230.     *  "comment" - Reason for the revision
  231.     *  "function" - Job function of individual performing revision
  232.     *  "name" - Name of the person who made the revision
  233.     *  "norm" - Date of the revision
  234.     *
  235.     * @access public
  236.     */
  237.     function getRevision()
  238.     {
  239.         return $this->m_akRevisions;
  240.     }
  241.  
  242.     /**
  243.     * Retrieve all headlines or a single headline denoted by key
  244.     *
  245.     * @return mixed 
  246.     *  Returns an array if no specific headline element is requested, or a string
  247.     *  if the specific headline element requested exists
  248.     *
  249.     * @param string 
  250.     *  The key value corresponding to the headline to be retrieved
  251.     *
  252.     * @access public
  253.     */
  254.     function getHeadline($nLevel = 1)
  255.     {
  256.         return $this->m_kHedlines["HL$nLevel"];
  257.     }
  258.  
  259.     /**
  260.     * Return information about the author of a document
  261.     *
  262.     * @param string 
  263.     *  The field of the byline to retrieve.
  264.     *
  265.     * @access public
  266.     */
  267.     function getByline($sProperty 'author')
  268.     {
  269.         $sProperty strtolower($sProperty);
  270.         if (isset ($this->m_kByline[$sProperty])) {
  271.  
  272.             return $this->m_kByline[$sProperty];
  273.  
  274.         }
  275.  
  276.         return null;
  277.     }
  278.  
  279.     /**
  280.     * Query for a list of related media elements
  281.     *
  282.     * @return array 
  283.     *  Returns an array of all media reference data, or an array of select media
  284.     *  reference data determined by the property parameter passed.
  285.     *
  286.     * @param string 
  287.     *  If supplied, only this property will be returned for each element of the
  288.     *  media reference array.
  289.     *
  290.     * @access public
  291.     */
  292.     function getMedia($sProperty = null)
  293.     {
  294.         if (empty ($sProperty)) {
  295.  
  296.             return $this->m_aMedia;
  297.  
  298.         }
  299.  
  300.         $aMediaRefs = array ();
  301.         foreach ($this->m_aMedia as $aMediaElem{
  302.  
  303.             if (isset ($aMediaElem[$sProperty])) {
  304.                 array_push($aMediaRefs$aMediaElem[$sProperty]);
  305.             }
  306.         }
  307.  
  308.         return $aMediaRefs;
  309.     }
  310.  
  311.     /**
  312.     * Returns the lede (sometimes called lead) paragraph
  313.     *
  314.     * @return string 
  315.     *  Returns the lede paragraph if it is defined, or null otherwise
  316.     *
  317.     * @access public
  318.     */
  319.     function getLede()
  320.     {
  321.         if (isset ($this->m_aContent[0])) {
  322.  
  323.             return $this->m_aContent[0];
  324.  
  325.         }
  326.         return null;
  327.     }
  328.  
  329.     /**
  330.     * Returns the paragraphs of content
  331.     *
  332.     * @return array 
  333.     *  An array of elements that represent a single paragraph each
  334.     *
  335.     * @access public
  336.     */
  337.     function getContent()
  338.     {
  339.         return $this->m_aContent;
  340.     }
  341.  
  342.     /**
  343.     * Returns the tag line (if one exists)
  344.     *
  345.     * @return string 
  346.     *  The tag line extracted from the NITF data source
  347.     *
  348.     * @access public
  349.     */
  350.     function getTagline()
  351.     {
  352.         return $this->m_sTagline;
  353.     }
  354.  
  355.     /**
  356.     * Returns the free-form bibliographic data
  357.     *
  358.     * @return string 
  359.     *  The bibliography (if one exists) is returned
  360.     *
  361.     * @access public
  362.     */
  363.     function getBibliography()
  364.     {
  365.         return $this->m_sBibliography;
  366.     }
  367.  
  368.     /**
  369.     * Get a string version of the article
  370.     *
  371.     * @return string 
  372.     *  A string representing the main headline, author, content, and tagline.
  373.     *
  374.     * @param string 
  375.     *  The character(s) used to separate each article element in the string that
  376.     *  is returned - often referred to as the CRLF.
  377.     *
  378.     * @access public
  379.     */
  380.     function toString($sCRLF "\n")
  381.     {
  382.         $sArticle = "{$this->m_kHedlines['HL1']}$sCRLF";
  383.  
  384.         if (!empty ($this->m_kByline['author'])) {
  385.  
  386.             $sArticle .= "{$this->m_kByline['author']}$sCRLF";
  387.  
  388.         }
  389.  
  390.         if (!empty ($this->m_sLocation)) {
  391.  
  392.             $sArticle .= "{$this->m_sLocation} - ";
  393.  
  394.         }
  395.  
  396.         $sArticle .= join($sCRLF, $this->m_aContent);
  397.  
  398.         if (!empty ($this->m_sTagline)) {
  399.  
  400.             $sArticle .= "$sCRLF{$this->m_sTagline}";
  401.  
  402.         }
  403.  
  404.         return $sArticle;
  405.     }
  406.  
  407.     /**
  408.     * Handle start XML elements and attributes
  409.     *
  410.     * When a new element is begun, this handler is executed.
  411.     *
  412.     * @param object
  413.     * The XML parser object instance that was inherited from the XML_Parser
  414.     * class
  415.     *
  416.     * @param string
  417.     * A tag element from the XML data stream
  418.     *
  419.     * @param array
  420.     * An array of XML attributes associated with the given tag supplied
  421.     *
  422.     * @access private
  423.     */
  424.     function StartHandler($oParser, $sName, $kAttrib)
  425.     {
  426.         // Push the element into the stack of XML elements already visited
  427.         array_push($this->m_aParentTags$sName);
  428.  
  429.         // Handle the attributes of the XML tags
  430.  
  431.         switch ($sName{
  432.  
  433.             case 'HL2' :
  434.                 $this->_sHedline = null;
  435.                 break;
  436.  
  437.             case 'P' :
  438.                 if (!empty ($kAttrib['LEDE']&& ($kAttrib['LEDE'== 'true')) {
  439.  
  440.                     $this->_bIsLede = true;
  441.  
  442.                 }
  443.                 $this->_sContent = null;
  444.                 break;
  445.  
  446.             case 'DOC.COPYRIGHT' :
  447.                 $this->m_kDocData['copyright'$kAttrib['HOLDER'];
  448.                 break;
  449.  
  450.             case 'MEDIA' :
  451.                 $this->_kMedia = array ();
  452.                 if (!empty ($kAttrib['MEDIA-TYPE'])) {
  453.  
  454.                     $this->_kMedia['type'$kAttrib['MEDIA-TYPE'];
  455.  
  456.                 } else {
  457.  
  458.                     $this->_kMedia['type''other';
  459.  
  460.                 }
  461.  
  462.                 $this->_kMedia['source'= null;
  463.                 $this->_kMedia['mime-type'= null;
  464.                 $this->_kMedia['caption'= null;
  465.                 $this->_kMedia['data'= null;
  466.                 $this->_kMedia['encoding'= null;
  467.                 $this->_kMedia['producer'= null;
  468.                 $this->_kMedia['meta'= array ();
  469.                 break;
  470.  
  471.             case 'MEDIA-REFERENCE' :
  472.                 if (!empty ($kAttrib['SOURCE'])) {
  473.  
  474.                     $this->_kMedia['source'$kAttrib['SOURCE'];
  475.  
  476.                     // Compatibility with the AP Usenet feed - note that this is a non
  477.                     // standard attribute and is NOT a part of NITF standards
  478.  
  479.                 }
  480.                 elseif (!empty ($kAttrib['DATA-LOCATION'])) {
  481.  
  482.                     $this->_kMedia['source'$kAttrib['DATA-LOCATION'];
  483.  
  484.                 }
  485.  
  486.                 $this->_kMedia['mime-type'$kAttrib['MIME-TYPE'];
  487.                 break;
  488.  
  489.             case 'MEDIA-OBJECT' :
  490.                 $this->_kMedia['encoding'$kAttrib['ENCODING'];
  491.                 break;
  492.  
  493.             case 'MEDIA-METADATA' :
  494.                 if (!empty ($kAttrib['NAME'])) {
  495.  
  496.                     $this->_kMedia[$kAttrib['NAME']] $kAttrib['VALUE'];
  497.  
  498.                 }
  499.                 break;
  500.  
  501.             case 'PUBDATA' :
  502.                 foreach ($kAttrib as $sKey => $sValue) {
  503.  
  504.                     $this->m_kPubData[strtolower($sKey)$sValue;
  505.  
  506.                 }
  507.                 break;
  508.  
  509.             case 'DOC-ID' :
  510.                 $this->m_kDocData['doc-id'$kAttrib['ID-STRING'];
  511.                 break;
  512.  
  513.                 // NITF 3.0 extension - added per request by Lars Schenk
  514.                 // (info@lars-schenk.de). Document urgency status information.
  515.  
  516.             case 'URGENCY' :
  517.                 $this->m_kDocData['urgency'$kAttrib['ED-URG'];
  518.                 break;
  519.  
  520.                 // The list of keywords or phrases are just added to the array of
  521.                 // keywords.
  522.  
  523.             case 'KEYWORD' :
  524.                 if (empty ($this->m_kDocData['key-list'])) {
  525.  
  526.                     $this->m_kDocData['key-list'= array ();
  527.  
  528.                 }
  529.  
  530.                 array_push($this->m_kDocData['key-list']$kAttrib['KEY']);
  531.                 break;
  532.  
  533.                 // The release, expiration, and issuing dates of this article. The
  534.                 // ISO-8601 time stamp settings are preserved, but you can use the
  535.                 // magic function strtotime() to convert these to time stamp values.
  536.  
  537.             case 'DATE.RELEASE' :
  538.             case 'DATE.EXPIRE' :
  539.             case 'DATE.ISSUE' :
  540.                 if (!empty ($kAttrib['NORM'])) {
  541.  
  542.                     $sName = strtolower($sName);
  543.                     $this->m_kDocData[$sName$kAttrib['NORM'];
  544.  
  545.                 }
  546.                 break;
  547.  
  548.             case 'REVISION-HISTORY' :
  549.                 array_push($this->m_akRevisionsarray_change_key_case($kAttribCASE_LOWER));
  550.                 break;
  551.  
  552.         }
  553.  
  554.     }
  555.  
  556.     /**
  557.     * Called when a tag element ends
  558.     *
  559.     * @param object
  560.     * The parser object parsing the XML data
  561.     *
  562.     * @param string
  563.     * The name of the tag element that has just ended
  564.     *
  565.     * @access private
  566.     */
  567.     function EndHandler($oParser, $sName)
  568.     {
  569.         switch ($sName) {
  570.  
  571.             case 'HL1' :
  572.                 $this->m_kHedlines['HL1'= trim($this->m_kHedlines['HL1']);
  573.                 break;
  574.  
  575.             case 'HL2' :
  576.                 array_push($this->m_kHedlines['HL2']trim($this->_sHedline));
  577.                 unset ($this->_sHedline);
  578.                 break;
  579.  
  580.             case 'P' :
  581.                 if (isset ($this->_bIsLede)) {
  582.  
  583.                     array_unshift($this->m_aContenttrim($this->_sContent));
  584.                     unset ($this->_bIsLede);
  585.  
  586.                 } else {
  587.  
  588.                     array_push($this->m_aContenttrim($this->_sContent));
  589.  
  590.                 }
  591.                 unset ($this->_sContent);
  592.                 break;
  593.  
  594.             case 'MEDIA' :
  595.                 array_push($this->m_aMedia$this->_kMedia);
  596.                 unset ($this->_kMedia);
  597.                 break;
  598.  
  599.         }
  600.  
  601.         array_pop($this->m_aParentTags);
  602.     }
  603.  
  604.     /**
  605.     * Handles CDATA sections from the XML document during processing
  606.     *
  607.     * @param object
  608.     * The XML parser instance inherited from the XML_Parser class
  609.     *
  610.     * @param string
  611.     * The data chunk to be processed from the parser
  612.     *
  613.     * @access private
  614.     */
  615.     function cdataHandler($oParser, $sData)
  616.     {
  617.         if (!in_array('MEDIA-OBJECT', $this->m_aParentTags)) {
  618.  
  619.             $sData = preg_replace('#\s+#', ' ', $sData);
  620.  
  621.         }
  622.  
  623.         // Elements that can be found in the BODY.HEAD section of the NITF
  624.         // document are defined in this handler.
  625.         if (in_array('BODY.HEAD', $this->m_aParentTags)) {
  626.  
  627.             // We don't care if they use other attribute items, we just want the
  628.             // textual version of the byline. Other attributes are appended to
  629.             // the byline data.
  630.             if (in_array('BYLINE', $this->m_aParentTags)) {
  631.  
  632.                 if (in_array('BYTTL', $this->m_aParentTags)) {
  633.  
  634.                     $this->m_kByline['title'.= $sData;
  635.                     return;
  636.  
  637.                 }
  638.  
  639.                 $this->m_kByline['author'.= $sData;
  640.                 return;
  641.  
  642.             }
  643.  
  644.             // Generally, the distributor is the same as the company supplying
  645.             // the content. However, this is not always the case (the AP, for
  646.             // example).
  647.             if (in_array('DISTRIBUTOR', $this->m_aParentTags)) {
  648.  
  649.                 $this->m_sDistributor .= $sData;
  650.                 return;
  651.  
  652.             }
  653.  
  654.             // The location where the story pertains too.
  655.             if (in_array('DATELINE', $this->m_aParentTags)) {
  656.  
  657.                 if (in_array('LOCATION', $this->m_aParentTags)) {
  658.  
  659.                     $this->m_sLocation .= $sData;
  660.  
  661.                 }
  662.                 return;
  663.             }
  664.  
  665.             // There are only two possibilities for hedlines, the main headline
  666.             // or a subheadline.
  667.             if (in_array('HEDLINE', $this->m_aParentTags)) {
  668.  
  669.                 if (in_array('HL2', $this->m_aParentTags)) {
  670.  
  671.                     $this->_sHedline .= $sData;
  672.  
  673.                 } else {
  674.  
  675.                     $this->m_kHedlines['HL1'.= $sData;
  676.  
  677.                 }
  678.  
  679.             }
  680.             return;
  681.  
  682.         }
  683.  
  684.         // The article content, including the lead and following paragraphs, can
  685.         // be found in this section of the XML document.
  686.         if (in_array('BODY.CONTENT', $this->m_aParentTags)) {
  687.  
  688.             if (in_array('MEDIA', $this->m_aParentTags)) {
  689.  
  690.                 // The media caption for the currently selected media element.
  691.                 if (in_array('MEDIA-CAPTION', $this->m_aParentTags)) {
  692.  
  693.                     $this->_kMedia['caption'.= $sData;
  694.                     return;
  695.  
  696.                 }
  697.  
  698.                 if (in_array('MEDIA-OBJECT', $this->m_aParentTags)) {
  699.  
  700.                     $this->_kMedia['data'.= $sData;
  701.                     return;
  702.  
  703.                 }
  704.  
  705.             }
  706.  
  707.             // A paragraph element was found.
  708.             if (in_array('P', $this->m_aParentTags)) {
  709.  
  710.                 $this->_sContent .= $sData;
  711.                 return;
  712.  
  713.             }
  714.  
  715.         }
  716.  
  717.         // The <body.end> tag has two primary elements, <taglines> and the free
  718.         // form <bibliography> tags.
  719.         if (in_array('BODY.END', $this->m_aParentTags)) {
  720.  
  721.             if (in_array('TAGLINE', $this->m_aParentTags)) {
  722.  
  723.                 $this->m_sTagline .= $sData;
  724.                 return;
  725.  
  726.             }
  727.  
  728.             if (in_array('BIBLIOGRAPHY', $this->m_aParentTags)) {
  729.  
  730.                 $this->m_sBibliography .= $sData;
  731.  
  732.             }
  733.  
  734.         }
  735.  
  736.     }
  737.  
  738. }
  739.  

Documentation generated on Mon, 11 Mar 2019 14:30:25 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.