simpleXml xml:lang
Ik weet dat er reeds over attributen en namespaces geschreven is, echter geen enkel toppic lijkt het correcte antwoord te bieden op volgende probleem:
<page>
<head>
<title xml:lang='en'><![CDATA[Blaap]]></title>
<title xml:lang='nl'><![CDATA[Toot]]></title>
</head>
</page>
Ik laad deze xml file in met simplexml_load_file.
echo $title = $xml->head->title;
zal me altijd 'Blaap' geven.
Hoe kan ik Toot terugkrijgen?
Reeds geprobeerd: namespaces met
$xml = simplexml_load_file($myFile);
$xml->registerXPathNamespace('xml', 'http://www.w3.org/2000/10/XMLSchema');
$title = $xml->head->xpath('/xml:title');
maar het ontglipt me steeds hoe ik te taal kan speciviceren.
Is er iemand die me een hint in de goeie richting kan geven?
Gewijzigd op 01/01/1970 01:00:00 door Sven
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$string = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<page>
<head>
<title xml:lang='en'><![CDATA[Blaap]]></title>
<title xml:lang='nl'><![CDATA[Toot]]></title>
</head>
</page>
XML;
$xml = simplexml_load_string($string);
$enresult = $xml->xpath("/page/head/title[@xml:lang='en']");
$nlresult = $xml->xpath("/page/head/title[@xml:lang='nl']");
echo $enresult[0] . PHP_EOL . $nlresult[0];
?>
$string = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<page>
<head>
<title xml:lang='en'><![CDATA[Blaap]]></title>
<title xml:lang='nl'><![CDATA[Toot]]></title>
</head>
</page>
XML;
$xml = simplexml_load_string($string);
$enresult = $xml->xpath("/page/head/title[@xml:lang='en']");
$nlresult = $xml->xpath("/page/head/title[@xml:lang='nl']");
echo $enresult[0] . PHP_EOL . $nlresult[0];
?>
Maar ik betwijfel het of het wel de netste methode is. Ook betwijfel ik of dat xml bestand wel valid is, aangezien de xml namespace nergens is gedeclareerd.
dank je voor het snelle antwoord.
Het werkt inderdaat met deze methode, echter niet zo elegant als ik het wou.
Ik plak hier later nog wel een update op dit scrip als ik't wat eleganter krijg.
Ivm je twijfels over de namespace:
ik maak enkel gebruik van de standaard namespace van xml:
http://www.w3.org/XML/1998/namespace
Ik heb de eerste regel zo aangepast:
<page xmlns:lang="http://www.w3.org/2000/10/XMLSchema">
Zowel dit als zonder de namespace uri lukt het om de xml file te valideren.
Ik zie het nu van die namespace, dat kon ik zostraks zo snel niet vinden...
np, ben al heel blij met je oplossing.
Zoals beloofd: een update.
Dankzij heel wat hulp van m'n beste collega jmoe er eindelijk uitgeraakt.
SimpleXML is Simple, maar dus niet om ingewikkelde dingen te doen.
Voor en nadelen?
+ Eenvoudige syntax
+ Eenvoudige funcites
+ gebruik van $xml->node->subnode notatie
- geen (goede) ondersteuning voor attributen
- eens je data in een SimpleXML object steekt is het nog moeilijk aan te passen (binnen dat object)
Conclusie: gebruik DOMelement voor bewerkingen, en laad die dan in in SimpleXML voor gemakkelijk gebruik.
Stukje code?
Om te vermijden dat je steeds op voorhand je path moet kennen (alsook de juiste xpath expressie (vb. [@xml:lang='nl']) in een situatie waaring je een xml als volgt opbouwd:
The XML:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<page>
<thetitle xml:lang='en'><![CDATA[en]]></thetitle>
<thetitle xml:lang='fr'><![CDATA[fr]]></thetitle>
<thetitle xml:lang='nl'><![CDATA[nl]]></thetitle>
<thetitle xml:lang='nl-BE'><![CDATA[nl]]></thetitle>
</page>
<page>
<thetitle xml:lang='en'><![CDATA[en]]></thetitle>
<thetitle xml:lang='fr'><![CDATA[fr]]></thetitle>
<thetitle xml:lang='nl'><![CDATA[nl]]></thetitle>
<thetitle xml:lang='nl-BE'><![CDATA[nl]]></thetitle>
</page>
De volgende code vereenvoudigd het selecteren van een node waarbij je een x-aantal nodes hebt voor verschillende talen alsook de mogelijkheid tot landspecifieke node.
De taal - locatie is op voorhand gekend en wordt meegegeven.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<?php
class StringBundle
{
const NAMESPACE_XML = 'http://www.w3.org/XML/1998/namespace';
protected $locale;
protected $language;
protected $xml;
/*construct the SimpleXML obj. without the unwanted nodes*/
public function __construct($identifier, $locale)
{
$this->language = strstr($this->locale, '-', true);
$xml = new \DOMDocument();
$elementFileName = $identifier.".xml";
$elementFilePath = "xml/".$elementFileName;
if(file_exists($elementFilePath))
{
$xml->load($elementFilePath);
$xml->saveXML();
$this->cleanThis($xml->documentElement);
}
$this->bundle = simplexml_import_dom($xml);
}
/**
* remove the unwanted lang
*/
protected function cleanThis(\DOMNode $node = null)
{
if ($node->hasChildNodes())
{
$localeNode = $langNode = null;
for ($i = $node->childNodes->length - 1; $i >= 0; $i--)
{
$child = $node->childNodes->item($i);
if (!$child instanceof \DOMElement)
{
continue;
}
if ($child->hasAttributeNS(self::NAMESPACE_XML, 'lang'))
{
$lang = $child->getAttributeNS(self::NAMESPACE_XML, 'lang');
if ($lang === $this->locale)
{
$localeNode = $child;
if ($langNode)
{
$langNode->parentNode->removeChild($langNode);
}
}
else if ($lang === $this->language && !$localeNode)
{
$langNode = $child;
}
else
{
$node->removeChild($child);
}
}
$this->removeUnwantedLocales($child);
}
}
}
/**
* Magic getter
* return SimpleXML
*/
public function __get($name)
{
return $this->bundle->$name;
}
}
?>
class StringBundle
{
const NAMESPACE_XML = 'http://www.w3.org/XML/1998/namespace';
protected $locale;
protected $language;
protected $xml;
/*construct the SimpleXML obj. without the unwanted nodes*/
public function __construct($identifier, $locale)
{
$this->language = strstr($this->locale, '-', true);
$xml = new \DOMDocument();
$elementFileName = $identifier.".xml";
$elementFilePath = "xml/".$elementFileName;
if(file_exists($elementFilePath))
{
$xml->load($elementFilePath);
$xml->saveXML();
$this->cleanThis($xml->documentElement);
}
$this->bundle = simplexml_import_dom($xml);
}
/**
* remove the unwanted lang
*/
protected function cleanThis(\DOMNode $node = null)
{
if ($node->hasChildNodes())
{
$localeNode = $langNode = null;
for ($i = $node->childNodes->length - 1; $i >= 0; $i--)
{
$child = $node->childNodes->item($i);
if (!$child instanceof \DOMElement)
{
continue;
}
if ($child->hasAttributeNS(self::NAMESPACE_XML, 'lang'))
{
$lang = $child->getAttributeNS(self::NAMESPACE_XML, 'lang');
if ($lang === $this->locale)
{
$localeNode = $child;
if ($langNode)
{
$langNode->parentNode->removeChild($langNode);
}
}
else if ($lang === $this->language && !$localeNode)
{
$langNode = $child;
}
else
{
$node->removeChild($child);
}
}
$this->removeUnwantedLocales($child);
}
}
}
/**
* Magic getter
* return SimpleXML
*/
public function __get($name)
{
return $this->bundle->$name;
}
}
?>
dus wanneer we nu een xml willen aanroepen in de juiste taal:
Gewijzigd op 01/01/1970 01:00:00 door Sven