PHP SimpleXML لا يحافظ على استراحات الخط في سمات XML

StackOverflow https://stackoverflow.com/questions/1457333

  •  12-09-2019
  •  | 
  •  

سؤال

لا بد لي من تحليل مقدمي خارجيا XML الذي يحتوي على سمات مع استراحة الأسطر فيها. باستخدام SimpleXML، يبدو أن استراحات السطر قد تضيع. وفق سؤال آخر Stackoverflow, ، يجب أن تكون استراحة السطر صالحة (على الرغم من أقل بكثير من المثالي!) ل XML.

لماذا فقدوا؟ [تعديل وكيف يمكنني الحفاظ عليها؟ /تعديل

فيما يلي برنامج نصي ملف تجريبي (لاحظ أنه عندما تكون فواصل الأسطر ليست في سمة يتم الحفاظ عليها).

ملف PHP مع XML مضمن

$xml = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<Rows>
    <data Title='Data Title' Remarks='First line of the row.
Followed by the second line.
Even a third!' />
    <data Title='Full Title' Remarks='None really'>First line of the row.
Followed by the second line.
Even a third!</data>
</Rows>
XML;

$xml = new SimpleXMLElement( $xml );
print '<pre>'; print_r($xml); print '</pre>';

الإخراج من print_r.

SimpleXMLElement Object
(
    [data] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [Title] => Data Title
                            [Remarks] => First line of the row. Followed by the second line. Even a third!
                        )

                )

            [1] => First line of the row.
Followed by the second line.
Even a third!
        )

)
هل كانت مفيدة؟

المحلول

الكيان لخط جديد هو &#10;. وبعد لقد لعبت مع الكود الخاص بك حتى وجدت شيئا فعلت الخدعة. إنه ليس أنيقا جدا، أحذرك:

//First remove any indentations:
$xml = str_replace("     ","", $xml);
$xml = str_replace("\t","", $xml);

//Next replace unify all new-lines into unix LF:
$xml = str_replace("\r","\n", $xml);
$xml = str_replace("\n\n","\n", $xml);

//Next replace all new lines with the unicode:
$xml = str_replace("\n","&#10;", $xml);

Finally, replace any new line entities between >< with a new line:
$xml = str_replace(">&#10;<",">\n<", $xml);

سيكون الافتراض، بناء على مثالك، أن أي خطوط جديدة تحدث داخل عقدة أو سمة سيكون لها نص آخر على السطر التالي، وليس < لفتح عنصر جديد.

ستفشل هذا بالطبع إذا كان لسطرك التالي نص نص ملفوف في عنصر على مستوى الخط.

نصائح أخرى

باستخدام SimpleXML، يبدو أن استراحات السطر قد تضيع.

نعم، من المتوقع أن ... في الواقع مطلوب من أي محلل XML مطابق يمكن أن تقوم Newlines في قيم السمة تمثل مسافات بسيطة. يرى تطبيع قيمة السمة في مواصفات XML.

إذا كان من المفترض أن تكون هناك حرفا جديدا حقيقيا في قيمة السمة، فيجب أن تضمن XML &#10; مرجع الأحرف بدلا من جديد خام.

بافتراض $ Xmldata هو سلسلة XML الخاصة بك قبل إرسالها إلى المحلل، يجب أن يحل هذا استبدال جميع الخطوط الجيوخية في السمات مع الكيان الصحيح. كان لدي مشكلة مع XML القادمة من SQL Server.

$parts = explode("<", $xmlData); //split over <
array_shift($parts); //remove the blank array element
$newParts = array(); //create array for storing new parts
foreach($parts as $p)
{
    list($attr,$other) = explode(">", $p, 2); //get attribute data into $attr
    $attr = str_replace("\r\n", "&#10;", $attr); //do the replacement
    $newParts[] = $attr.">".$other; // put parts back together
}
$xmlData = "<".implode("<", $newParts); // put parts back together prefixing with <

ربما يمكن القيام به ببساطة مع Regex، ولكن هذه ليست نقطة قوية بالنسبة لي.

فيما يلي رمز لاستبدال الأسطر الجديدة مع مرجع الأحرف المناسبة في جزء XML معين. قم بتشغيل هذا الرمز قبل التحليل.

$replaceFunction = function ($matches) {
    return str_replace("\n", "&#10;", $matches[0]);
};
$xml = preg_replace_callback(
    "/<data Title='[^']+' Remarks='[^']+'/i",
    $replaceFunction, $xml);

هذا هو ما عمل لي:

أولا، احصل على XML كسلسلة:

    $xml = file_get_contents($urlXml);

ثم القيام بديل:

    $xml = str_replace(".\xe2\x80\xa9<as:eol/>",".\n\n<as:eol/>",$xml);

ال "." و "<as: EOL />" كانت هناك لأنني بحاجة إلى إضافة فترات راحة في هذه الحالة. يمكن استبدال الخطوط الجديدة " n" بكل ما تريد.

بعد استبدال، قم فقط بتحميل سلسلة XML ككائن بسيط:

    $xmlo = new SimpleXMLElement( $xml );

et voilà.

حسنا، هذا السؤال قديم ولكن مثلي، قد يأتي شخص ما إلى هذه الصفحة في نهاية المطاف. كان لدي نهج مختلف قليلا وأعتقد أن الأكثر أناقة من هذه المذكورة.

داخل XML، تضع بعض الكلمة الفريدة التي ستستخدمها لسطر جديد.

تغيير XML إلى

<data Title='Data Title' Remarks='First line of the row. \n
Followed by the second line. \n
Even a third!' />

ثم عند الحصول على مسار للعقدة المطلوبة في SimpleXML في إخراج السلسلة، اكتب شيئا مثل هذا:

$findme  = '\n';
$pos = strpos($output, $findme);
if($pos!=0)
{
$output = str_replace("\n","<br/>",$output);

لا يجب أن يكون " n"، يمكن أن يكون أي شار فريد من نوعه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top