1: <?php
2: /**
3: * This code is licensed under AGPLv3 license or Afterlogic Software License
4: * if commercial version of the product was purchased.
5: * For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
6: */
7:
8: namespace Aurora\System\Xml;
9:
10: /**
11: * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
12: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
13: * @copyright Copyright (c) 2019, Afterlogic Corp.
14: *
15: * @package Api
16: */
17: class Document
18: {
19: /**
20: * @var Node
21: */
22: public $XmlRoot = null;
23:
24: /**
25: * @var array
26: */
27: protected $_stack = null;
28:
29: /**
30: * @param string $sName
31: * @param string $sValue
32: */
33: public function CreateElement($sName, $sValue = null)
34: {
35: $this->XmlRoot = new Node($sName, $sValue);
36: }
37:
38: /**
39: * @param string $sXmlText
40: * @return bool
41: */
42: public function ParseFromString($sXmlText)
43: {
44: $bResult = false;
45: if (!empty($sXmlText)) {
46: $oParser = xml_parser_create();
47: xml_parser_set_option($oParser, XML_OPTION_CASE_FOLDING, false);
48: xml_parser_set_option($oParser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
49: // xml_parser_set_option($oParser, XML_OPTION_SKIP_WHITE, true);
50:
51: xml_set_element_handler(
52: $oParser,
53: array(&$this, '_startElement'),
54: array(&$this, '_endElement')
55: );
56:
57: xml_set_character_data_handler($oParser, array(&$this, '_charData'));
58:
59: $bResult = xml_parse($oParser, $sXmlText);
60: if (!$bResult) {
61: $sError = xml_error_string(xml_get_error_code($oParser));
62: }
63: xml_parser_free($oParser);
64: }
65:
66: return (bool) $bResult;
67: }
68:
69: /**
70: * @param bool $bSplitLines
71: * @return string
72: */
73: public function ToString($bSplitLines = false)
74: {
75: $sOutStr = '<'.'?'.'xml version="1.0" encoding="utf-8"?'.'>';
76: if ($bSplitLines) {
77: $sOutStr .= "\r\n";
78: }
79:
80: if (null !== $this->XmlRoot) {
81: $sOutStr .= $this->XmlRoot->ToString($bSplitLines);
82: }
83:
84: return $sOutStr;
85: }
86:
87: /**
88: * @param string $sFileName
89: * @return bool
90: */
91: public function LoadFromFile($sFileName)
92: {
93: $sXmlData = @file_get_contents($sFileName);
94: if (false !== $sXmlData) {
95: return $this->ParseFromString($sXmlData);
96: }
97: return false;
98: }
99:
100: /**
101: * @param string $sFileName
102: * @return bool
103: */
104: public function SaveToFile($sFileName)
105: {
106: $bResult = false;
107: $rFilePointer = @fopen($sFileName, 'wb');
108: if ($rFilePointer) {
109: $bResult = (false !== @fwrite($rFilePointer, $this->ToString(true)));
110: $bResult = @fclose($rFilePointer);
111: }
112:
113: return $bResult;
114: }
115:
116: /**
117: * @param string $sName
118: * @return string
119: */
120: public function GetParamValueByName($sName)
121: {
122: $oParam =& $this->getParamNodeByName($sName);
123: return (null !== $oParam && isset($oParam->Attributes['value']))
124: ? \Aurora\System\Utils::DecodeSpecialXmlChars($oParam->Attributes['value']) : '';
125: }
126:
127: /**
128: * @param string $sName
129: * @return string
130: */
131: public function GetParamTagValueByName($sName)
132: {
133: $oParam =& $this->getParamNodeByName($sName);
134: return (null !== $oParam) ? \Aurora\System\Utils::DecodeSpecialXmlChars($oParam->Value) : '';
135: }
136:
137: /**
138: * @param string $sName
139: * @return object
140: */
141: protected function &getParamNodeByName($sName)
142: {
143: $iNodeKey = null;
144: $oNull = null;
145: if ($this->XmlRoot && is_array($this->XmlRoot->Children)) {
146: $aNodeKeys = array_keys($this->XmlRoot->Children);
147: foreach ($aNodeKeys as $iNodeKey) {
148: if ($this->XmlRoot->Children[$iNodeKey]->TagName == 'param' &&
149: isset($this->XmlRoot->Children[$iNodeKey]->Attributes['name']) &&
150: $this->XmlRoot->Children[$iNodeKey]->Attributes['name'] == $sName) {
151: return $this->XmlRoot->Children[$iNodeKey];
152: }
153: }
154: }
155: return $oNull;
156: }
157:
158: /**
159: * @access private
160: * @param object $oParser
161: * @param string $sName
162: * @param array $aAttributes
163: */
164: public function _startElement($oParser, $sName, $aAttributes)
165: {
166: $this->_nullFunction($oParser);
167: $oNode = new Node($sName);
168: $oNode->Attributes = $aAttributes;
169: if ($this->XmlRoot == null) {
170: $this->XmlRoot =& $oNode;
171: } else {
172: $oRootNode = null;
173: $oRootNode =& $this->_stack[count($this->_stack) - 1];
174: $oRootNode->Children[] =& $oNode;
175: }
176:
177: $this->_stack[] =& $oNode;
178: }
179:
180: /**
181: * @access private
182: */
183: public function _endElement()
184: {
185: array_pop($this->_stack);
186: }
187:
188: /**
189: * @access private
190: * @param object $oParser
191: * @param string $sText
192: */
193: public function _charData($oParser, $sText)
194: {
195: $oNode = null;
196: $this->_nullFunction($oParser);
197: $oNode =& $this->_stack[count($this->_stack) - 1];
198: if ($oNode->Value == null) {
199: $oNode->Value = '';
200: }
201:
202: if ($sText == '>') {
203: $oNode->Value .= '&gt;';
204: } elseif ($sText == '<') {
205: $oNode->Value .= '&lt;';
206: } else {
207: $oNode->Value .= $sText;
208: }
209: }
210:
211: /**
212: * @access private
213: * @return bool
214: */
215: public function _nullFunction()
216: {
217: return true;
218: }
219: }
220: