Asked  7 Months ago    Answers:  5   Viewed   37 times

I have a previously generated XML like this:

<newsletter>

    <header>
        </magazine>
        </image>
        <strap/>
    </header>

    <intro>
        <date/>
        <text/>
        </edimg>
    </intro>

    <shop>
        <heading/>
        <article/>
        <title/>
        <img/>
        <link/>
        <excerpt/>
    </shop>

    <sidebar>
        <cover/>
        <cover_link/>
        <text/>
        <advert>
        <link/>
        <image/>
        </advert>
    </sidebar>

</newsletter>

I need to be able to insert an element in between the <intro> and the <shop> elements

this:

$section = $dom->documentElement->appendChild($dom->createElement('section'));

will just create the element within <newsletter> .

I assumed this would be fairly simple , but cannot seem to find a solution .

Thanks.

 Answers

92

You might try this; I didn't test it, but the solution comes from using insertBefore instead of appendChild.

$shop = $dom->getElementsByTagName("shop")->item(0);
$section = $dom->documentElement->insertBefore($dom->createElement('section'),$shop);
Wednesday, March 31, 2021
 
aaronhuisinga
answered 7 Months ago
49

The answer is that it doesn't actually need any escaping according to the spec (skipping the mentions of CDATA):

The ampersand character (&) and the left angle bracket (<) must not appear in their literal form (...) If they are needed elsewhere, they must be escaped using either numeric character references or the strings " &amp; " and " &lt; " respectively. The right angle bracket (>) may be represented using the string " &gt; " (...)

To allow attribute values to contain both single and double quotes, the apostrophe or single-quote character (') may be represented as " &apos; ", and the double-quote character (") as " &quot; ".

You can verify this easily by using createTextNode() to perform the correct escaping:

$dom = new DOMDocument;
$e = $dom->createElement('description');
$content = 'single quote: ', double quote: ", opening tag: <, ampersand: &, closing tag: >';
$t = $dom->createTextNode($content);
$e->appendChild($t);
$dom->appendChild($e);

echo $dom->saveXML();

Output:

<?xml version="1.0"?>
<description>single quote: ', double quote: ", opening tag: &lt;, ampersand: &amp;, closing tag: &gt;</description>
Saturday, May 29, 2021
 
nika
answered 5 Months ago
34

Using recursion, you can create a brand new document based on the input, solving all your points at once:

Code

<?php

$input = file_get_contents('http://www.fluffyduck.com.au/sampleXML.xml');
$inputDoc = new DOMDocument();
$inputDoc->loadXML($input);

$outputDoc = new DOMDocument("1.0", "utf-8");
$outputDoc->appendChild($outputDoc->createElement("root"));

function ConvertUserToItem($outputDoc, $inputNode, $outputNode)
{
    if ($inputNode->hasChildNodes())
    {
        foreach ($inputNode->childNodes as $inputChild)
        {
            if (strtolower($inputChild->nodeName) == "user")
            {
                $outputChild = $outputDoc->createElement("item");
                $outputNode->appendChild($outputChild);
                // read input attributes and convert them to nodes
                if ($inputChild->hasAttributes())
                {
                    $outputContent = $outputDoc->createElement("content");
                    foreach ($inputChild->attributes as $attribute)
                    {
                        if (strtolower($attribute->name) != "id")
                        {
                            $outputContent->appendChild($outputDoc->createElement($attribute->name, $attribute->value));
                        }
                        else
                        {
                            $outputChild->setAttribute($attribute->name, $attribute->value);
                        }
                    }               
                    $outputChild->appendChild($outputContent);
                }
                // recursive call
                ConvertUserToItem($outputDoc, $inputChild, $outputChild);
            }
        }
    }
}

ConvertUserToItem($outputDoc, $inputDoc->documentElement, $outputDoc->documentElement);

header("Content-Type: text/xml; charset=" . $outputDoc->encoding);
echo $outputDoc->saveXML();
?>

Output

<?xml version="1.0" encoding="utf-8"?>
<root>
    <item id="41">
        <content>
            <username>bsmain</username>
            <firstname>Boss</firstname>
            <lastname>MyTest</lastname>
            <fullname>Test Name</fullname>
            <email>lalal@test.com</email>
            <logins>1964</logins>
            <lastseen>11/09/2012</lastseen>
        </content>
        <item id="61">
            <content>
                <username>underling</username>
                <firstname>Under</firstname>
                <lastname>MyTest</lastname>
                <fullname>Test Name</fullname>
                <email>lalal@test.com</email>
                <logins>4</logins>
                <lastseen>08/09/2009</lastseen>
            </content>
        </item>
...
Saturday, May 29, 2021
 
lechup
answered 5 Months ago
25

The content property states:

Authors may include newlines in the generated content by writing the "A" escape sequence in one of the strings after the 'content' property. This inserted line break is still subject to the 'white-space' property. See "Strings" and "Characters and case" for more information on the "A" escape sequence.

So you can use:

#headerAgentInfoDetailsPhone:after {
  content:"Office: XXXXX A Mobile: YYYYY ";
  white-space: pre; /* or pre-wrap */
}

http://jsfiddle.net/XkNxs/

When escaping arbitrary strings, however, it's advisable to use 0000a instead of A, because any number or [a-f] character followed by the new line may give unpredictable results:

function addTextToStyle(id, text) {
  return `#${id}::after { content: "${text.replace(/"/g, '\"').replace(/n/g, '\00000a')} }"`;
}
Wednesday, June 2, 2021
 
WooDzu
answered 5 Months ago
21

You need to import any node to append it to another document:

$departmentArray->item($i)->appendChild( $doc->importNode( $employee, true ) );
Friday, August 6, 2021
 
previous_developer
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :