-2

I am curious if I can search an XML file for a certain tag with regular expressions. I can search the file if I use fopen('foo.xml'); but it will only allow me to search the content between the tags not the tags them self. My objective for this is I hope to create a function that will allow me to delete all the content between two tags for example between users which are in a xml file. He language that I am using is PHP.

Thanks in advance john.

john
  • 23
  • 5
  • 1
    I wouldn't recommend using regular expressions. See https://stackoverflow.com/questions/3577641/how-do-you-parse-and-process-html-xml-in-php for better alternatives – Phil Jun 28 '18 at 00:41
  • Please post sample data and sample code for what you've tried. As far as regex, the Ungreedy modifier `U` will help you with this. – mike.k Jun 28 '18 at 00:41
  • okay will try using the SimpleXML library or the DOM thanks phil. – john Jun 28 '18 at 00:58
  • We really need to see a minimal, yet accurate, representation of your xml; your coding attempt; and your expected result. – mickmackusa Jun 28 '18 at 01:32

3 Answers3

0

You should use something like SimpleXMLto handle/edit XML files.

If you really insist on doing it by treating the SML file as a string you can do something like this (or you can use regex). But you should use an XML library.

// get your file as a string 
$yourXML = file_get_contents($file) ;

$posStart = stripos($yourXML,'<users>') + strlen('<users>') ;
$posEnd = stripos($yourXML,'</users>')  ;

$newXML = substr($yourXML,0,$posStart) . substr($yourXML,$posEnd) ;

// <users> is now empty
echo $newXML ;
Mr Glass
  • 1,186
  • 1
  • 6
  • 14
0

DomDocument & XPath will make things very clean, direct and reliable.

You can use evaluate() or query() as they provide the same result.

// will seek out the matching tags regardless of their location.

Be aware that my solution is case-sensitive.

Code: (Demo)

$xml = <<<XML
<myXml>
<Person>
  <firstName>pradeep</firstName>
  <lastName>jain</lastName>
  <address>
    <doorNumber>287</doorNumber>
    <street>2nd block</street>
    <city>bangalore</city>
  </address>
  <phoneNums type="mobile">9980572765</phoneNums>
  <phoneNums type="landline">080 42056434</phoneNums>
  <phoneNums type="skype">123456</phoneNums>
</Person>
<Person>
  <firstName>pradeep</firstName>
  <lastName>jain</lastName>
  <address>
    <doorNumber>287</doorNumber>
    <street>2nd block</street>
    <city>bangalore</city>
  </address>
  <phoneNums type="mobile">1</phoneNums>
  <phoneNums type="landline">2</phoneNums>
  <phoneNums type="skype">3</phoneNums>
</Person>
</myXml>
XML;

$dom = new DOMDocument; 
$dom->loadXML($xml);  // <-- you'll need to import your file instead of a string as demo'ed here
$xpath = new DOMXPath($dom);
echo count($xpath->evaluate("//phoneNums")) , "\n";  // 6
echo count($xpath->evaluate("//street")) , "\n";  // 2
echo count($xpath->evaluate("//myXml")) , "\n";  // 1
echo count($xpath->evaluate("//Person")) , "\n";  // 2
echo count($xpath->evaluate("//person")) , "\n";  // 0 <-- case-sensitive
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0

As a simple mock up of the various parts needed to do this in SimpleXML, there are a few concepts you need to know to get it to work.

The main one being XPath, which a sort of SQL for XML. Of course it has it's own notation and can be a little pedantic at times, but you can experiment with it on sites like https://codebeautify.org/Xpath-Tester.

$data = '<?xml version="1.0" encoding="UTF-8"?>
<Users>
    <User id="123">
        <Name>fred</Name>
        <Extension>1234</Extension>
    </User>
    <User id="124">
        <Name>bert</Name>
        <Extension>1235</Extension>
    </User>
    <User id="125">
        <Name>foo</Name>
        <Extension>1236</Extension>
    </User>
</Users>';

$userID = "123";

$users = simplexml_load_string($data);

// Find the user with the id attribute (use [0] as the call to xpath 
// returns a list of matches and you only want the first one)
$userMatch = $users->xpath("//User[@id='{$userID}']")[0];

// Just output user id attribute and name
echo "id=".$userMatch['id'].",name=".$userMatch->Name.PHP_EOL;
echo "Removing user...".PHP_EOL;

// Remove the user - note the [0] is required here
unset($userMatch[0]);

// Print out the resulting XML after the removal
echo $users->asXML();

I've put comments through the code as how it works. The output is...

id=123,name=fred
Removing user...
<?xml version="1.0" encoding="UTF-8"?>
<Users>

    <User id="124">
        <Name>bert</Name>
        <Extension>1235</Extension>
    </User>
    <User id="125">
        <Name>foo</Name>
        <Extension>1236</Extension>
    </User>
</Users>
Nigel Ren
  • 56,122
  • 11
  • 43
  • 55