PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/extensions/SemanticMediaWiki/includes/sparql/SMW_SparqlResultParser.php

https://github.com/ChuguluGames/mediawiki-svn
PHP | 153 lines | 76 code | 15 blank | 62 comment | 25 complexity | 67fee3b6e2a39d6c43e65f76ffa2b8cb MD5 | raw file
  1. <?php
  2. /**
  3. * Parser class for the SPARQL XML result format.
  4. *
  5. * @file
  6. * @ingroup SMWSparql
  7. *
  8. * @author Markus Krötzsch
  9. */
  10. /**
  11. * Class for parsing SPARQL results in XML format.
  12. *
  13. * @since 1.6
  14. *
  15. * @ingroup SMWSparql
  16. */
  17. class SMWSparqlResultParser {
  18. /**
  19. * Associative array mapping SPARQL variable names to column indices.
  20. * @var array of integer
  21. */
  22. protected $m_header;
  23. /**
  24. * List of result rows. Individual entries can be null if a cell in the
  25. * SPARQL result table is empty (this is different from finding a blank
  26. * node).
  27. * @var array of array of (SMWExpElement or null)
  28. */
  29. protected $m_data;
  30. /**
  31. * List of comment strings found in the XML file (without surrounding
  32. * markup, i.e. the actual string only).
  33. * @var array of string
  34. */
  35. protected $m_comments;
  36. /**
  37. * Stack of open XML tags during parsing.
  38. * @var array of string
  39. */
  40. protected $m_xml_opentags;
  41. /**
  42. * Integer index of the column that the current result binding fills.
  43. * @var integer
  44. */
  45. protected $m_xml_bindidx;
  46. /**
  47. * Datatype URI for the current literal, or empty if none.
  48. * @var string
  49. */
  50. protected $m_xml_datatype;
  51. /**
  52. * Parse the given XML result and return an SMWSparqlResultWrapper for
  53. * the contained data.
  54. *
  55. * @param $xmlQueryResult string
  56. */
  57. public function makeResultFromXml( $xmlQueryResult ) {
  58. $parser = xml_parser_create();
  59. xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 0 );
  60. xml_parser_set_option( $parser, XML_OPTION_TARGET_ENCODING, 'UTF-8' );
  61. xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 );
  62. xml_set_object( $parser, $this );
  63. xml_set_element_handler( $parser, 'xmlHandleOpen', 'xmlHandleClose' );
  64. xml_set_character_data_handler($parser, 'xmlHandleCData' );
  65. xml_set_default_handler( $parser, 'xmlHandleDefault' );
  66. //xml_set_start_namespace_decl_handler($parser, 'xmlHandleNsDeclaration' );
  67. $this->m_xml_opentags = array();
  68. $this->m_header = array();
  69. $this->m_data = array();
  70. $this->m_comments = array();
  71. xml_parse( $parser, $xmlQueryResult, true );
  72. xml_parser_free( $parser );
  73. return new SMWSparqlResultWrapper( $this->m_header, $this->m_data, $this->m_comments );
  74. }
  75. protected function xmlHandleDefault( $parser, $data ) {
  76. if ( substr( $data, 0, 4 ) == '<!--' ) {
  77. $comment = substr( $data, 4, strlen( $data ) - 7 );
  78. $this->m_comments[] = trim( $comment );
  79. }
  80. }
  81. /**
  82. * Handle an opening XML tag during parsing.
  83. * @see xml_set_element_handler
  84. */
  85. protected function xmlHandleOpen( $parser, $tagName, $attributes ) {
  86. $prevTag = end( $this->m_xml_opentags );
  87. $this->m_xml_opentags[] = $tagName;
  88. if ( ( $tagName == 'binding' ) && ( $prevTag == 'result' ) ) {
  89. if ( ( array_key_exists( 'name', $attributes ) ) &&
  90. ( array_key_exists( $attributes['name'], $this->m_header ) ) ) {
  91. $this->m_xml_bindidx = $this->m_header[$attributes['name']];
  92. }
  93. } elseif ( ( $tagName == 'result' ) && ( $prevTag == 'results' ) ) {
  94. $row = array();
  95. for ( $i = 0; $i < count( $this->m_header ); ++$i ) {
  96. $row[$i] = null;
  97. }
  98. $this->m_data[] = $row;
  99. } elseif ( ( $tagName == 'literal' ) && ( $prevTag == 'binding' ) ) {
  100. if ( array_key_exists( 'datatype', $attributes ) ) {
  101. $this->m_xml_datatype = $attributes['datatype'];
  102. } else {
  103. $this->m_xml_datatype = false;
  104. }
  105. /// TODO handle xml:lang attributes here as well?
  106. } elseif ( ( $tagName == 'variable' ) && ( $prevTag == 'head' ) ) {
  107. if ( array_key_exists( 'name', $attributes ) ) {
  108. $this->m_header[$attributes['name']] = count( $this->m_header );
  109. }
  110. }
  111. }
  112. /**
  113. * Handle a closing XML tag during parsing.
  114. * @see xml_set_element_handler
  115. */
  116. protected function xmlHandleClose( $parser, $tagName ) {
  117. array_pop( $this->m_xml_opentags );
  118. }
  119. /**
  120. * Handle XML character data during parsing.
  121. * @see xml_set_character_data_handler
  122. */
  123. protected function xmlHandleCData( $parser, $dataString ) {
  124. $prevTag = end( $this->m_xml_opentags );
  125. $rowcount = count( $this->m_data );
  126. if ( $prevTag == 'uri' ) {
  127. $this->m_data[$rowcount-1][$this->m_xml_bindidx] = new SMWExpResource( $dataString );
  128. } elseif ( $prevTag == 'literal' ) {
  129. $this->m_data[$rowcount-1][$this->m_xml_bindidx] = new SMWExpLiteral( $dataString, $this->m_xml_datatype );
  130. } elseif ( $prevTag == 'bnode' ) {
  131. $this->m_data[$rowcount-1][$this->m_xml_bindidx] = new SMWExpResource( '_' . $dataString );
  132. } elseif ( $prevTag == 'boolean' ) { // no "results" in this case
  133. $literal = new SMWExpLiteral( $dataString, 'http://www.w3.org/2001/XMLSchema#boolean' );
  134. $this->m_data = array( array( $literal ) );
  135. $this->m_header = array( '' => 0 );
  136. }
  137. }
  138. }