| 1882 | } |
| 1883 | |
| 1884 | char* XMLElement::ParseAttributes(char* p, int* curLineNumPtr) |
| 1885 | { |
| 1886 | XMLAttribute* prevAttribute = 0; |
| 1887 | |
| 1888 | // Read the attributes. |
| 1889 | while (p) |
| 1890 | { |
| 1891 | p = XMLUtil::SkipWhiteSpace(p, curLineNumPtr); |
| 1892 | if (!(*p)) |
| 1893 | { |
| 1894 | _document->SetError(XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name()); |
| 1895 | return 0; |
| 1896 | } |
| 1897 | |
| 1898 | // attribute. |
| 1899 | if (XMLUtil::IsNameStartChar(*p)) |
| 1900 | { |
| 1901 | XMLAttribute* attrib = CreateAttribute(); |
| 1902 | TIXMLASSERT(attrib); |
| 1903 | attrib->_parseLineNum = _document->_parseCurLineNum; |
| 1904 | |
| 1905 | int attrLineNum = attrib->_parseLineNum; |
| 1906 | |
| 1907 | p = attrib->ParseDeep(p, _document->ProcessEntities(), curLineNumPtr); |
| 1908 | if (!p || Attribute(attrib->Name())) |
| 1909 | { |
| 1910 | DeleteAttribute(attrib); |
| 1911 | _document->SetError(XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name()); |
| 1912 | return 0; |
| 1913 | } |
| 1914 | // There is a minor bug here: if the attribute in the source xml |
| 1915 | // document is duplicated, it will not be detected and the |
| 1916 | // attribute will be doubly added. However, tracking the 'prevAttribute' |
| 1917 | // avoids re-scanning the attribute list. Preferring performance for |
| 1918 | // now, may reconsider in the future. |
| 1919 | if (prevAttribute) |
| 1920 | { |
| 1921 | TIXMLASSERT(prevAttribute->_next == 0); |
| 1922 | prevAttribute->_next = attrib; |
| 1923 | } |
| 1924 | else |
| 1925 | { |
| 1926 | TIXMLASSERT(_rootAttribute == 0); |
| 1927 | _rootAttribute = attrib; |
| 1928 | } |
| 1929 | prevAttribute = attrib; |
| 1930 | } |
| 1931 | // end of the tag |
| 1932 | else if (*p == '>') |
| 1933 | { |
| 1934 | ++p; |
| 1935 | break; |
| 1936 | } |
| 1937 | // end of the tag |
| 1938 | else if (*p == '/' && *(p + 1) == '>') |
| 1939 | { |
| 1940 | _closingType = CLOSED; |
| 1941 | return p + 2; // done; sealed element. |
nothing calls this directly
no test coverage detected