解析XML文件时如何处理默认名称空间

时间:2019-06-26 12:04:57

标签: php xml-parsing xml-namespaces domxpath xliff

我的PHP页面必须解析输入的XML文件(准确地说是XLIFF),但是当XML文件的根元素中存在默认名称空间时,该页面不起作用。

我的代码假定默认名称空间是必需的,并且它必须为urn:oasis:names:tc:xliff:document:1.2。如果在XLIFF根元素中找到,则从那里获取,否则由我的PHP代码添加。我以为这是可行的,但似乎不可行,此刻,我唯一可行的唯一方法是从输入XLIFF文件中删除默认名称空间。当然,无论XLIFF文件中是否存在默认名称空间,PHP脚本都应该起作用。

在了解必须使用默认名称空间的情况下,在我的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

     

object(DOMNodeList)#12(1){     [“ length”] =>     整数(2)   }

$tus数组在XLIFF文件中包含两个trans-unit节点。

但是,当文件包含

<?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:names:tc:xliff:document:1.2

     

object(DOMNodeList)#10(1){     [“ length”] =>     整数(0)   }

如您所见,$tus数组为空。

一个潜在的解决方案是在再次添加名称空间声明之前先删除它,但是我想了解问题出在哪里。谢谢。

1 个答案:

答案 0 :(得分:0)

似乎只有在XML文件中存在名称空间时才有必要将名称空间添加到xpath,因此:

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

但是,我不确定这在其他情况下是否会适得其反...

当它不存在时,似乎没有必要将其包含在xpath表达式中:

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