Как обрабатывать пространства имен по умолчанию при разборе файлов XML - PullRequest
1 голос
/ 26 июня 2019

Моя страница PHP должна анализировать входные XML-файлы (точнее, XLIFF), но она не работает, если в корневом элементе XML-файла присутствует пространство имен по умолчанию.

В моем коде предполагается, что требуется пространство имен по умолчанию и оно должно быть urn:oasis:names:tc:xliff:document:1.2. Если он найден в корневом элементе XLIFF, он извлекается оттуда, иначе он добавляется моим PHP-кодом. Я думал, что это работает, но, похоже, это не так, и на данный момент единственный способ заставить его работать - удалить пространство имен по умолчанию из входного файла XLIFF. Конечно, скрипт PHP должен работать независимо от того, присутствует ли пространство имен по умолчанию в файле XLIFF или нет.

При понимании того, что пространство имен по умолчанию необходимо, в моем PHP-скрипте я имею:

$xml_file = file_get_contents($pathToInputFile);
if($xml_file === FALSE) {
    die("there is a problem to get contents from XLIFF file");
} 

$xliffObj = new DOMDocument();
$xliffObj->preserveWhiteSpace = true;
$xliffObj->loadXML($xml_file);

$context = $xliffObj->documentElement;
$xpath = new DOMXPath($xliffObj);

if (isSet($context->getAttributeNode('xmlns')->nodeValue)) {
    $ns = $context->getAttributeNode('xmlns')->nodeValue; 
    echo "The ns is: " . $ns;                          // line 198
}
else {
    $ns = "urn:oasis:names:tc:xliff:document:1.2";
    // this works when no default namespaces is defined in the XLIFF file
    echo "I have defined the ns as: " . $ns; 
}

$xpath->registerNamespace('ns', $ns);                 // line 208

$tus = $xpath->query('//trans-unit');
var_dump_pre($tus);die;

Разбор работает нормально, если мой входной файл XLIFF имеет:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd">
<xliff xmlns:pisa="http://www.ets.org/pisa" version="1.2">

В этом случае вывод будет

Я определил ns как: urn: oasis: names: tc: xliff: document: 1.2

объект (DOMNodeList) # 12 (1) { [ "Длина"] => Int (2) }

Массив $tus содержит два узла trans-unit в файле XLIFF.

Однако, когда файл имеет

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd">
<xliff xmlns:pisa="http://www.ets.org/pisa" version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">

тогда ничего не извлекается и массив, в котором я сохраняю содержимое файла, пуст (имеет значение NULL). Выход:

ns: urn: oasis: имена: tc: xliff: документ: 1.2

объект (DOMNodeList) # 10 (1) { [ "Длина"] => Int (0) }

Как видите, массив $tus пуст.

Потенциальным решением может быть простое удаление объявления пространства имен перед его повторным добавлением, но я бы хотел понять, в чем проблема. Спасибо.

1 Ответ

0 голосов
/ 26 июня 2019

Кажется необходимым добавлять пространство имен в xpath только тогда, когда оно присутствует в файле XML, таким образом:

$xpath->registerNamespace('ns', $ns);
$tus = $xpath->query('//ns:trans-unit');

Однако я не уверен, что это может иметь неприятные последствия в других ситуациях ...

Когда его нет, кажется, нет необходимости включать его в выражение xpath:

#$xpath->registerNamespace('ns', $ns);
$tus = $xpath->query('//trans-unit');
...