0

I have an xml document that has nodes mixed in with text. I want to parse this node as bold text in-line with the existing text. I have searched and researched the web for answers but fail to find the way to do this. My xml file looks like this:

<song>
  <lyrics>
    <verse name="v1">
      <lines>
        On a <chord name="A"/>hill far away stood an <chord name="D"/>old rugged cross, The <chord name="E7"/>emblem of suff'ring and <chord name="A"/>shame;<br/>
        And I <chord name="A"/>love that old cross where the <chord name="D"/>dearest and best, For a <chord name="E7"/>world of lost sinners was <chord name="A"/>slain.
      </lines>
    </verse>
  </lyrics>
</song>

To parse the text of the verse I have done:

$xml = @simplexml_load_file($file) or die("Can't read XML-SONG file...");
$myVerse= $xml->lyrics->verse[0]->lines;
echo $myVerse;

which prints:

On a hill far away stood an old rugged cross, The emblem of suff'ring and shame; And I love that old cross where the dearest and best, For a world of lost sinners was slain.

But how do I parse those <chord name="D"/ > as (bold) text in between the text?..

2
  • Can you please provide an example of what the output actually should look like? Commented Jan 23, 2015 at 15:31
  • It would be nice if i could do: On a (A) hill far away stood an (D) old rugged cross Commented Jan 23, 2015 at 16:30

3 Answers 3

0

the simplexml_load_file was not passing your chord tags at all. I made that assumption in my first post. The actual XML produced from the load was

SimpleXMLElement Object
(
    [lyrics] => SimpleXMLElement Object
        (
            [verse] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [name] => v1
                        )

                    [lines] => 
        On a hill far away stood an old rugged cross, The emblem of suff'ring and shame;
        And I love that old cross where the dearest and best, For a world of lost sinners was slain
                )
        )
)

So I switched to use DOM instead and was still getting the chord tags stripped out since they are invalid. I found some help in this thread PHP DOM get nodevalue html? (without stripping tags)

I ended with this. Which does what you want.

<?php

function get_inner_html( $node ) { 
    $innerHTML= ''; 
    $children = $node->childNodes; 
    foreach ($children as $child) { 
        $innerHTML .= $child->ownerDocument->saveXML( $child ); 
    } 

    return $innerHTML;  
} 

$file='myxmlfile.xml';
$doc = new DOMDocument();
$doc->load($file);
$lines=$doc->getElementsByTagName('lines');
$linesarray=array();
foreach ($lines as $node) {
  $linesarray[]=get_inner_html($node);
}

foreach($linesarray as $myVerse){
    $regex='/(<chord name="(.{1,2})"\/>)/';
    $replacement = '<B>$2</B> ';
    $myVerse= preg_replace($regex,$replacement,$myVerse);
    echo $myVerse;
}

?>

Which gives a result of

On a A hill far away stood an D old rugged cross, The E7 emblem of suff'ring and A shame;
And I A love that old cross where the D dearest and best, For a E7 world of lost sinners was A slain.

Sign up to request clarification or add additional context in comments.

1 Comment

your method works and therefor I will grant you the benefit of the correct answer, however, I will end up using my ->asXML() answer as it requires less code. I believe yours is technically the right way though ;-)
0
$xml = @simplexml_load_file($file) or die("Can't read XML-SONG file...");
$myVerse= $xml->lyrics->verse[0]->lines;

$regex='/(<chord name="(.{1,2})"\/>)/';
$replacement = '<B>$2</B> ';
$myVerse= preg_replace($regex,$replacement,$myVerse);
echo $myVerse;

This will output

On a A hill far away stood an D old rugged cross, The E7 emblem of suff'ring and A shame;

You can modify the replacement string to suit your needs for displaying the chords.

3 Comments

I tried replacing but this doesn't seem to work because when you 'print_r' the $myVerse, it only shows the array details, yet when i echo $myVerse, it just prints the plain verse text without the <chord> nodes
Edited my answer to include your beginning lines. This will output it with the BOLDED chord letters in placed of <chord name="E7"/> .
I've tried it but it doesn't work. I don't know why but when I echo $myVerse it doesn't show the <chord> nodes at all, however when I print_r($myVerse) it shows me a complicated array like this: SimpleXMLElement Object ( [chord] => Array ( [0] => SimpleXMLElement Object ( [@attributes] => Array ( [name] => A ) ) [1] => SimpleXMLElement Object ( [@attributes] => Array ( [name] => D ) ) [2] => SimpleXMLElement Object ( [@attributes] => Array ( [name] => E7 ) ) [3] => Sim...
0

Okay, the issue why the chord node was not showing up when printed as echo $myVerse (even in the page source where the node should be able to show up) is because I forgot to output my $myVerse asXML(). Therefore the variable should be changed like this:

$xml = @simplexml_load_file($file) or die("Can't read XML-SONG file...");
$myVerse= $xml->lyrics->verse[0]->lines;->asXML();

When we print this in the page, then we can see the node in the page-source

echo $myVerse;

Only then can we replace the node the way @greg_diesel suggested like:

$regex='/(<chord name="(.{1,2})"\/>)/';
$replacement = '<B>$2</B> ';
$myVerse= preg_replace($regex,$replacement,$myVerse);
echo $myVerse;

Thanks @greg_diesel but the answer was in the ->asXML() The research has helped me to learn xml a bit better, let me hope this helps someone else as well!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.