ILMV Posted August 26, 2009 Share Posted August 26, 2009 Hello again, still battling with my XML I have one final problem, here is a piece of example XML: <feed> <title>My XML Feed</title> <other_tag a='1' b='2' c='other' /> <author>ILMV</author> </feed> If you can see I have a tag called "other_tag", which contains 3 attributes and is self closing. I need to convert those attributes to child tags and create a independant closing tag, such as this: <feed> <title>My XML Feed</title> <other_tag> <a>1</a> <b>2</b> <c>other</c> </other_tag> <author>ILMV</author> </feed> *It doesn't have to be indented Like I said in my other post, I am a regex n00b... I think this could be done in one shot, but I am unsure. Any help greatly appreciated, Many thanks, Ben Quote Link to comment https://forums.phpfreaks.com/topic/171917-xml-attributes-to-tags-remove-self-closing/ Share on other sites More sharing options...
Adam Posted August 26, 2009 Share Posted August 26, 2009 Is the syntax *always*: a='...' b='...' c='...' ? Quote Link to comment https://forums.phpfreaks.com/topic/171917-xml-attributes-to-tags-remove-self-closing/#findComment-906510 Share on other sites More sharing options...
ILMV Posted August 26, 2009 Author Share Posted August 26, 2009 No, the attribute names and content could be anything, and the quantity of attributes may differ as well, for example there may be none, there may be seven. Quote Link to comment https://forums.phpfreaks.com/topic/171917-xml-attributes-to-tags-remove-self-closing/#findComment-906512 Share on other sites More sharing options...
Adam Posted August 26, 2009 Share Posted August 26, 2009 Jeez. This is the best I could come up with I'm affraid: if (preg_match_all('/<other_tag(.*?)\/>/', $xml, $tag_matches)) { if (preg_match_all('/([^=]+)=(\'|")([^\'"]*)(\'|")/', $tag_matches[1][0], $param_matches)) { $nex_xml = '<other_tag>'; foreach ($param_matches[1] as $key => $param) { $new_xml .= '<' . trim($param_matches[1][$key]) . '>' . $param_matches[3][$key] . '</' . trim($param_matches[1][$key]) . '>'; } $nex_xml .= '</other_tag>'; } $xml = str_replace($tag_matches[0][0], $new_xml, $xml); } I dare say someone will come along with a tidier / different version. Quote Link to comment https://forums.phpfreaks.com/topic/171917-xml-attributes-to-tags-remove-self-closing/#findComment-906519 Share on other sites More sharing options...
ILMV Posted August 26, 2009 Author Share Posted August 26, 2009 Many thanks for your help MrAdam! I have forgotten to mention that <othertag /> could be anything as well (e.g. <foo /> <bar />) :-/, s**t. However, I will take what you have coded and do my best to not screw it up Again, many thanks! Ben Quote Link to comment https://forums.phpfreaks.com/topic/171917-xml-attributes-to-tags-remove-self-closing/#findComment-906525 Share on other sites More sharing options...
ILMV Posted August 26, 2009 Author Share Posted August 26, 2009 Ah, I have found a problem, it is matching the first < it finds, and trawling through until it finds a />. which means it will find this: <feed> <title>My XML Feed</title> <other_tag a='1' b='2' c='other' /> Is there a way to specify that the starting character should be <, but until a /> is found we don't want to match any other < ? Thanks, Ben Quote Link to comment https://forums.phpfreaks.com/topic/171917-xml-attributes-to-tags-remove-self-closing/#findComment-906557 Share on other sites More sharing options...
Adam Posted August 26, 2009 Share Posted August 26, 2009 I'd recommend reading this: http://www.regular-expressions.info/possessive.html Quote Link to comment https://forums.phpfreaks.com/topic/171917-xml-attributes-to-tags-remove-self-closing/#findComment-906560 Share on other sites More sharing options...
ILMV Posted August 26, 2009 Author Share Posted August 26, 2009 Right, I have spent hours looking over this and I still cannot understand how to clear this final hurdle. I have a vague idea as to how I think the problem can be resolved, but I am relying on guess work as I cant understand this possessive quantifiers lark. As I have to check that only one < exists I assumed that I have to do this: ([<]?????)([A-Za-z0-9_]+)(.*?) \/\> ..putting a ([<]) in will allow my to specify a quantifier.... right? Quote Link to comment https://forums.phpfreaks.com/topic/171917-xml-attributes-to-tags-remove-self-closing/#findComment-906668 Share on other sites More sharing options...
Maq Posted August 26, 2009 Share Posted August 26, 2009 A simpler and safer solution would be to use SimpleXML. You can easily test for empty attributes, self-terminating elements, empty nodes, etc. with XPath. Quote Link to comment https://forums.phpfreaks.com/topic/171917-xml-attributes-to-tags-remove-self-closing/#findComment-906679 Share on other sites More sharing options...
ILMV Posted August 26, 2009 Author Share Posted August 26, 2009 Oh I am going to cry I used this code to find self terminating tags: $sxml = new SimpleXMLElement($xml, LIBXML_NOEMPTYTAG); From the Googling I had done I was under the impression that would convert a tag like <this /> into a tag like <this></this>, and it did on some of the tags in my feed (Google Calendar feed) but not all of them. Quote Link to comment https://forums.phpfreaks.com/topic/171917-xml-attributes-to-tags-remove-self-closing/#findComment-906685 Share on other sites More sharing options...
thebadbad Posted August 28, 2009 Share Posted August 28, 2009 Maq is absolutely right, but here's another way of doing it: <?php $source = "<feed> <title>My XML Feed</title> <other_tag a='1' b='2' c='other' /> <author>ILMV</author> </feed>"; function func_callback($matches) { $count = preg_match_all('~([a-z0-9_:.-]+)\s*=\s*[\'"](.*?)[\'"]~is', $matches[2], $pairs); $matches[0] = ''; for ($i = 0; $i < $count; $i++) { $matches[0] .= "<{$pairs[1][$i]}>{$pairs[2][$i]}</{$pairs[1][$i]}>"; } return "<{$matches[1]}>{$matches[0]}</{$matches[1]}>"; } $source = preg_replace_callback('~<([a-z0-9_:.-]+)\s+([^>]+?)/>~i', 'func_callback', $source); ?> Quote Link to comment https://forums.phpfreaks.com/topic/171917-xml-attributes-to-tags-remove-self-closing/#findComment-908244 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.