Remove Child不包含属性值



我正在练习XML DOM PHP解析。我有这样的XML文件(较短的版本):

<?xml version="1.0" encoding="UTF-8"?>
<tabela_kursow typ="A" uid="21a184">
<numer_tabeli>184/A/NBP/2021</numer_tabeli>
<data_publikacji>2021-09-22</data_publikacji>
<pozycja>
<nazwa_waluty>bat (Tajlandia)</nazwa_waluty>
<przelicznik>1</przelicznik>
<kod_waluty>THB</kod_waluty>
<kurs_sredni>0,1181</kurs_sredni>
</pozycja>
<pozycja>
<nazwa_waluty id="2">dolar amerykański</nazwa_waluty>
<przelicznik>1</przelicznik>
<kod_waluty>USD</kod_waluty>
<kurs_sredni>3,9460</kurs_sredni>
</pozycja>
</tabela_kursow>

我创建了名称"id"价值"2">

<?php
$doc = new DOMDocument();
$doc->load("kursy_walut.xml");
$doc->preserveSpace = false;
$doc->formatOutput = true;

$a = $doc->getElementsByTagName("nazwa_waluty");
$b = count($a);
for ($i=0; $i<$b; $i++){
$c = $a[$i]->childNodes[0]->nodeValue;
if ($c === 'dolar amerykański'){
$a[$i]->setAttribute('id', '2');
}
if ($c === 'euro'){
$a[$i]->setAttribute('id', '2');
}
}
$doc->save('output.xml');

现在我想:

  1. 只获取不包含的标签元素
  2. 包含属性'id="2">
  3. 只获取包含的标签元素只有"id ="2";"。

对于第一种情况,我创建了这样的代码。不知道如何创建第二个case

$doc3 = new DOMDocument();
$doc3->preserveWhiteSpace = false;
$doc3->load('output.xml');
$xpath2 = new DOMXPath($doc3);
$id3 = $xpath2->query('//*/pozycja/nazwa_waluty[@id="2"]');
foreach($id3 as $attr){
$attr->parentNode->removeChild($attr);
}
$doc3->formatOutput = true;
$doc3->save('output3.xml');
也许有人能帮我解决第二个问题?谢谢你。

如果我理解你的来源,那么你想根据货币字符串添加一个id。但是,您正在使用特定于语言的字符串。语言代码将是一个更好的选择。它已经被定义和唯一了。

DOMNode::getElementsByTagName()返回一个节点列表,您可以使用foreach来迭代它。然而,节点列表是"live"的。它对节点上的变化作出反应。如果您添加/删除节点,这是一个问题。使用Xpath表达式可以避免这种情况,并允许更具体的获取。

更重要的是,看看DOMNode::$textContent属性。它读取/写入节点内的整个文本。对于元素,这包括任何后代文本节点。

可以简化代码:

$document = new DOMDocument();
// configure the parser - need to be set before load
$document->preserveWhiteSpace = false;
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$currencyMap = [
"USD" => 2,
"EUR" => 4
];
// iterate the "nazwa_waluty" elements
foreach ($xpath->evaluate('//pozycja/kod_waluty') as $kodWaluty) {
// get the currency code
$currencyCode = trim($kodWaluty->textContent);
if (isset($currencyMap[$currencyCode])) {
// add id for currency
$kodWaluty->setAttribute('id', $currencyMap[$currencyCode]);
}
}
// configure the serializer - need to be set before save
$document->formatOutput = true;
echo $document->saveXML();

输出:

<?xml version="1.0" encoding="UTF-8"?>
<tabela_kursow typ="A" uid="21a184">
<numer_tabeli>184/A/NBP/2021</numer_tabeli>
<data_publikacji>2021-09-22</data_publikacji>
<pozycja>
<nazwa_waluty>bat (Tajlandia)</nazwa_waluty>
<przelicznik>1</przelicznik>
<kod_waluty>THB</kod_waluty>
<kurs_sredni>0,1181</kurs_sredni>
</pozycja>
<pozycja>
<nazwa_waluty>dolar amerykański</nazwa_waluty>
<przelicznik>1</przelicznik>
<kod_waluty id="2">USD</kod_waluty>
<kurs_sredni>3,9460</kurs_sredni>
</pozycja>
</tabela_kursow>

现在获取具有特定id的数据。我希望您需要pozycja元素及其子元素。

DOMXpath::evaluate()不仅可以返回节点列表,还可以返回标量值。没有那么多代码:

foreach ($xpath->evaluate('//pozycja[kod_waluty/@id = "2"]') as $pozycja) {
var_dump(
[
'przelicznik' => $xpath->evaluate('string(przelicznik)', $pozycja),
'kurs_sredni' => $xpath->evaluate('string(kurs_sredni)', $pozycja),
]
);
}

输出:

array(2) {
["przelicznik"]=>
string(1) "1"
["kurs_sredni"]=>
string(6) "3,9460"
}

但是,由于语言代码已经定义并且是唯一的,您可以直接使用它:

foreach ($xpath->evaluate('//pozycja[normalize-space(kod_waluty) = "USD"]') as $pozycja) {
var_dump(
[
'przelicznik' => $xpath->evaluate('string(przelicznik)', $pozycja),
'kurs_sredni' => $xpath->evaluate('string(kurs_sredni)', $pozycja),
]
);
}

如果你需要"kurs_serdni"那么您可以使用单个Xpath表达式:

var_dump(
$xpath->evaluate(
'string(//pozycja[normalize-space(kod_waluty) = "USD"]/kurs_sredni)'
)
);

输出:

string(6) "3,9460"

最新更新