在节点值上运行PHP函数然后输出XML?

时间:2014-11-25 13:15:55

标签: php xml dom encryption

我有一个来自file_get_contents的XML。它包含一堆值,包括<strStringValue>内的加密值。我有一个将解密它们的函数,我试图使用这个代码,但它只打印出strStringValue中的值:

    <?php
if (!isset($HTTP_RAW_POST_DATA)) {
    $HTTP_RAW_POST_DATA = file_get_contents("php://input"); 
    $doc = new DOMDocument();
    $doc->loadXML($HTTP_RAW_POST_DATA);
    $stringvalue = $doc->getElementsByTagName('strStringValue');
    foreach ($stringvalue as $strstringvalue) {
             echo $strstringvalue->nodeValue, PHP_EOL;
    }

    include("Decrypt1.php");
    $in = "$strstringvalue";

    $HTTP_RAW_POST_DATA2=Decrypt1($in);
    echo("$HTTP_RAW_POST_DATA2");
    }
?>

以下是XML的示例:

加密

<string>
<Id>1</Id>
<strStringCaption>file-commision</strStringCaption>
<strStringValue enc="0">2734sad87asd78asdt8a7d6874slwe9832t</strStringValue>
</string>
<string>
<Id>2</Id>
<strStringCaption>file-shop</strStringCaption>
<strStringValue enc="0">78sd7asgd87adg87g873g78dad</strStringValue>
</string>

解密的

<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>
<string>
<string>

1 个答案:

答案 0 :(得分:1)

您可以通过XSL(T)XSLTProcessor::registerPHPFunctions

来完成

(对不起大量的样板代码)

<?php
echo "\r\n------- src -------\r\n";
$xml = getDocData();
echo $xml;

echo "\r\n------- process #1 (encrypt) -------\r\n";
$xml = process($xml);
echo $xml;

echo "\r\n------- process #2 (decrypt) -------\r\n";
$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;
}

打印

------- 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>

但如何摆脱@!#§! xmlns:php="http://php.net/xsl"属性现在超出了我的能力范围。

<xsl:template match="@*|node()">是一个基本的“copy-it-all模板”。它几乎匹配任何没有“更好”匹配的东西,只是按原样将源节点复制到目标。

<xsl:template match="strStringValue[@enc='0']">是与未加密的strStringValue元素匹配的模板,并通过myEncrypt($plain)将目标与加密版本“替换”。

<xsl:template match="strStringValue[@enc='1']">通过myDecrypt($encrypted)执行相反的操作。