Wednesday, May 26, 2010

merge two XML by PHP; Replace Nodes

Merging two XML files is just painful, especially if you have complex files. Here is the best way and most efficient way that I have found after researching a lot. It is still complected by I think it would be great. imagine you got two XML files as below:

(?php
$xml1 = (((XML
(?xml version="1.0"?)
(family)
(parent)
(child1)child 1(/child1)
(child2)child 1.1(/child2)
(/parent)
(/family)
XML;
?)

(?php
$xml2 = (((XML
(?xml version="1.0"?)
(family)
(parent)
(child1)child 1(/child1)
(child2)child 2.1(/child2)
(/parent)
(/family)
XML;
?)

You want to merge them together, but the most complicated part is, your manager ask you to replace the node value of child2 with node value of child1; on the other hand, do not change the node name... So, the only thing that you should do is copy and paste the following code and it 100% works!!!! :D

(?php
loadXML($xml1);
$xpathT1 = new DOMXpath($xliffT1);
$nodeListT1 = $xpathT1->query('/family/parent/child2');

$xliffT2 = new DomDocument;
$xliffT2->loadXML($xml2);

$xpathT2 = new DOMXpath($xliffT2);
$nodeListT2 = $xpathT2->query('/family/parent/child1');
$nodeListTargetT2 = $xpathT2->query('/family/parent/child2');

mergeXliffFiles($xliffT1, $nodeListT1, $xliffT2, $nodeListT2, $nodeListTargetT2);


function mergeXliffFiles($xliffT1, $nodeListT1, $xliffT2, $nodeListT2, $nodeListTargetT2){

for($i=0; $i< $nodeListT2->length; $i++){
$xliffT1Node = $xliffT1->createElement('Child1', $nodeListT1->item($i)->nodeValue);
$xliffT1->appendChild($xliffT1Node);
$xliffT1Node->setAttribute('xml:lang','fr-FR');
$newnode = $xliffT2->importNode($xliffT1->getElementsByTagName('Child1')->item($i), true);
$oldnode = $nodeListT2->item($i);
$oldnode->parentNode->replaceChild($newnode, $oldnode);

$xliffT2Node = $xliffT2->createElement('Child2', $nodeListTargetT2->item($i)->nodeValue);
$xliffT2->appendChild($xliffT2Node);
$xliffT2Node->setAttribute('xml:lang','fr-FR');
$newnode2 = $xliffT2->importNode($xliffT2->getElementsByTagName('Child1')->item($i), true);
$oldnode2 = $nodeListTargetT2->item($i);
$oldnode2->parentNode->replaceChild($xliffT2Node, $oldnode2);
}

$xpathNew = new DOMXpath($xliffT2);
$nodelistNew = $xpathNew->query('/family/parent');

$j = 0;
foreach($nodelistNew as $node){
$source[0] = $xliffT2->getElementsByTagName('Child1')->item(0);
$asb = $xliffT2->createElement('child1', $source[0]->nodeValue);
$source[0]->parentNode->replaceChild($asb, $source[0]);

$target[0] = $xliffT2->getElementsByTagName('Child2')->item(0);
$asb = $xliffT2->createElement('child2', $target[0]->nodeValue);
$target[0]->parentNode->replaceChild($asb, $target[0]);
$j++;

}

$xliffT2->save('test2.xml');
}
?>

What you are gonna have on test2.xml is something like that:

(family)
(parent)
(child1)child 1.1(/child1)
(child2)child 2.1(/child2)
(/parent)
(/family)

Monday, July 10, 2006

Internationalization (i18n) and Multi bundling in Java web tier

I am going to describe basic concepts for i18n (internationalization), how to write and configure an internationalized software, and how to modify and internationalize a software. In addtion, I will write my experieces about this concept.

firstly, I stronglly belive that you must know something about resource bundles, because i18n doesnt have any meaning without resource bundle. So, after you get come knowlage about it come back and continues your reading :D I was kidding with you, I will describe it brieflly. in old version of programing, you have a jsp or html page like this:

user-name : < input type="text"... />

and if you have some other pages which need to show user-name, you have to write it in each page. Consequentlly, if you want to change for example, user-name to UserName you must change them in all of your pages. It is a very heigh risk action. So, for preventing this we write our caption in resource bundle file (.properties) instead of write them in jsp pages. For this, you just create a property file with an optional name, I recommende ApplicationResources.properties and place it in WEB-INF below, for example, /WEB-INF/ApplicationResources.properties. In addition, if you use struts web framework you should change your struts-config.xml as below:

< message-resources parameter="ApplicationResources"/>

and declare your captions in this file. Each cption has 2 parts, key and description. for above example, I will write userName = user-name in resource bundle file. userName is key and user-name is description of it. Now, your jsp page will be like this: < input type="text".../> well, if you want to change user-name to UserName you just change your property file then deploy your project and enjoy it ;)

Now back to main subject i18n, for this one you can make some other property files with the same name(like this, Application ApplicationResources_xx.properties, xx will be changed for each language) beneath the main resource file(for above example ApplicationResources.properties) for each language. for example if you want to make an application with 2 languages Farsi and English, make Application ApplicationResources_en.properties fo English and Application ApplicationResources_fa.properties for Farsi. all of the keys have to the same, but, the description defined for each language. look the following sample:

# ApplicationResources_en.properties
userName = user-name

# ApplicationResources_fa.properties
userName = كاربر

Now, if you change your locale the struts controller change user-name to كاربر.

after that, your projst is like this:

WEB-INF
|
-----ApplicationResources // the main propery file
|
ApplicationResources_en.properties
ApplicationResources_fa.properties

Moreover, I have to add this note that you dont have to write anything in the main property file, but there is this question, what is the default file? for answer to this question you must change your web.xml like this:

< context-param>
< param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale
< param-value>en


In this one, the default file is ApplicationResources_en.properties and if your locale is for example, es, your application shown in English.

JSTL

If you use JSFT tags instead of struts tags, you must declare it in your web.xml as described it:

< context-param>
< param-name>javax.servlet.jsp.jstl.fmt.localizationContext
< param-value>ApplicationResources


and use < fmt:message key="userName"/> in your jsp page.

Multi Resource Bundle

you can have 2 or more property file, for this, you have to declare 2 or more files and write them in struts-config.xml as I mentioned and use bean tag of struts in your jsp page.

for example you have 2 files named, ApplicationResources.properties and orod.properties was located under WEB-INF, so your struts-config.xml will be like this:

< message-resources parameter="ApplicationResources"/>
< message-resources parameter="orod"/>

and write hello = hello in ApplicationResources_en.properties and write bye = bye in orod.properties. when you use will be printed hello in jsp and when you use printed bye in the jsp.

But, if use JSTL instead of struts tags, you have to change web.xml as above and set bundle to introduce specific bundle before < fmt:message .../> by < fmt:setBundle basename="orod"/> or < fmt:bundle basename="orod">

have a good time and enjoy i18n

Sunday, January 01, 2006

Oracle Flashback Technology is an absolutly fabulous feature

As you know, we're living in "Information Era", so data and informatiom is one of the most wealthy thing of us. Consequently, Backup and Recovery of this data is one of the major problem of DBAs. Oracle 10g represent a new facility to solve this problem easily, it is called "Oracle Flashback Technology". It faster and more efficient than Point_in_Time recovery. This technology consists of 6 types:
• Oracle Flashback Query
• Oracle Flashback Version Query
• Oracle Flashback Transaction Query
• Oracle Flashback Table
• Oracle Flashback Drop
• Oracle Flashback Database

Oracle Flashback Query: Recovering at the Row Level
If you know 'JOHN' was at 09:30:00, but it is deleted, you can find it as below:
SQL> SELECT * FROM EMPLOYEE AS OF TIMESTAMP
TO_TIMESTAMP ('2003-04-04 09:30:00', 'YYYY-MM-DD HH:MI:SS')
WHERE name = 'JOHN';
You can insert deleted 'JOHN' to EMPLOYEE as below:
SQL> INSERT INTO employee
(SELECT * FROM employee AS OF TIMESTAMP
TO_TIMESTAMP ('2003-04-04 09:30:00', 'YYYY-MM-DD HH:MI:SS')
WHERE name = 'JOHN');

Oracle Flashback Table
SQL> FLASHBACK TABLE employee TO TIMESTAMP
TO_TIMESTAMP ('2003-04-04 09:30:00', `YYYY-MM-DD HH24:MI:SS');

Oracle Flashback Drop: Undo a DROP TABLE Operation
SQL> show recyclebin;
SQL> SELECT object_name as recycle_name, original_name, object_type
FROM recyclebin;

Oracle Flashback Database
RMAN> FLASHBACK DATABASE
TO TIME to_timestamp ('2002-11-11 16:00:00', 'YYYY-MM-DD HH24:MI:SS');
SQL> FLASHBACK DATABASE
TO TIME to_timestamp ('2002-11-11 16:00:00', 'YYYY-MM-DD HH24:MI:SS');