You could do it via XSL(T) and XSLTProcessor::registerPHPFunctions
(sorry for the tons and tons of boilerplate code)
<?php
echo "
------- src -------
";
$xml = getDocData();
echo $xml;
echo "
------- process #1 (encrypt) -------
";
$xml = process($xml);
echo $xml;
echo "
------- process #2 (decrypt) -------
";
$xml = process($xml);
echo $xml;
function myEncrypt($plain) {
// just a demo, not even pretending to do proper encryption
return 'sosecret:'.strrev($plain);
}
function myDecrypt($encrypted) {
$prefix = 'sosecret:';
$cbPrefix = strlen($prefix);
if ( 0===strncmp($encrypted, $prefix, $cbPrefix) ) {
return strrev(substr($encrypted, $cbPrefix));
}
return 'error';
}
function process($xml) {
$processor = getXSLT(getStyleData());
$doc = getDocument($xml);
return $processor->transformToXML($doc);
}
function getXSLT($xml) {
$doc = getDocument($xml);
$proc = new XSLTProcessor();
$proc->registerPHPFunctions( array('myEncrypt', 'myDecrypt'));
$proc->importStyleSheet($doc);
return $proc;
}
function getDocument($xml) {
$doc = new DOMDocument;
$doc->loadxml($xml);
return $doc;
}
function getDocData() {
return <<< EOX
<doc>
<string>
<Id>1</Id>
<strStringCaption>file-commision</strStringCaption>
<strStringValue enc="0">commisions.txt</strStringValue>
</string>
<string>
<Id>2</Id>
<strStringCaption>file-shop</strStringCaption>
<strStringValue enc="0">shoplist.xml</strStringValue>
</string>
</doc>
EOX;
}
function getStyleData() {
return <<< EOX
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
<xsl:output method="xml"/>
<xsl:template match="strStringValue[@enc='0']">
<strStringValue enc="1">
<xsl:value-of select="php:function('myEncrypt',string(.))"/>
</strStringValue>
</xsl:template>
<xsl:template match="strStringValue[@enc='1']">
<strStringValue enc="0">
<xsl:value-of select="php:function('myDecrypt',string(.))"/>
</strStringValue>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
EOX;
}
prints
------- src -------
<doc>
<string>
<Id>1</Id>
<strStringCaption>file-commision</strStringCaption>
<strStringValue enc="0">commisions.txt</strStringValue>
</string>
<string>
<Id>2</Id>
<strStringCaption>file-shop</strStringCaption>
<strStringValue enc="0">shoplist.xml</strStringValue>
</string>
</doc>
------- process #1 (encrypt) -------
<?xml version="1.0"?>
<doc>
<string>
<Id>1</Id>
<strStringCaption>file-commision</strStringCaption>
<strStringValue xmlns:php="http://php.net/xsl" enc="1">sosecret:txt.snoisimmoc</strStringValue>
</string>
<string>
<Id>2</Id>
<strStringCaption>file-shop</strStringCaption>
<strStringValue xmlns:php="http://php.net/xsl" enc="1">sosecret:lmx.tsilpohs</strStringValue>
</string>
</doc>
------- process #2 (decrypt) -------
<?xml version="1.0"?>
<doc>
<string>
<Id>1</Id>
<strStringCaption>file-commision</strStringCaption>
<strStringValue xmlns:php="http://php.net/xsl" enc="0">commisions.txt</strStringValue>
</string>
<string>
<Id>2</Id>
<strStringCaption>file-shop</strStringCaption>
<strStringValue xmlns:php="http://php.net/xsl" enc="0">shoplist.xml</strStringValue>
</string>
</doc>
but how to get rid of the @!#§! xmlns:php="http://php.net/xsl"
attribute is beyond my capabilities right now.
<xsl:template match="@*|node()">
is a basic "copy-it-all template". It matches almost anything that has no "better" match and just copies the source node as-is to the target.
<xsl:template match="strStringValue[@enc='0']">
is the template that matches the strStringValue elements that are not encrypted and "replaces" it in the target with the encrypted version via myEncrypt($plain)
.
<xsl:template match="strStringValue[@enc='1']">
does the reverse thing via myDecrypt($encrypted)
.