如何使用PHP将XML与不同结构相结合?

时间:2016-07-29 08:26:40

标签: php xml

我查看了几个问题和文档以及部分代码,但我不知道自己做错了什么。

我需要将8个不同的XML组合成一个XML,最终将是1个html文件。 XML的文件名是动态生成的。在示例中,我只使用了2个xml文件。

变量中的XML1:$ file_xml_cv

<?xml version="1.0" encoding="UTF-8"?>
    <node>
      <cv>
        <cvid>584</cvid>
        <titel>Dit is een test cv</titel>
        <naam>DHR H.V.H. Dagobert Duck</naam>
      </cv>
    </node>

varbele $ file_xml_werkgevers中的XML2

<?xml version="1.0" encoding="UTF-8"?>
    <node>
      <werkgevers>
        <naam>Company 1</naam>
        <Functie>Projectmanager en Informatie analist</Functie>
        <periode>1967-01-01 00:00:00</periode>
        <einddatum>1967-01-01 00:00:00</einddatum>
      </werkgevers>
      <werkgevers>
        <naam>Company 2</naam>
        <Functie>Systeemontwerper</Functie>
        <periode/>
        <einddatum/>
      </werkgevers>
    </node>

哪个应该导致XML3

<?xml version="1.0" encoding="UTF-8"?>
<node>
    <cv>
       <cvid>584</cvid>
       <titel>Dit is een test cv</titel>
       <naam>DHR H.V.H. Dagobert Duck</naam>
    </cv>
    <werkgevers>
       <naam>Company 1</naam>
       <Functie>Projectmanager en Informatie analist</Functie>
       <periode>1967-01-01 00:00:00</periode>
       <einddatum>1967-01-01 00:00:00</einddatum>
     </werkgevers>
     <werkgevers>
        <naam>Company 2</naam>
        <Functie>Systeemontwerper</Functie>
        <periode/>
        <einddatum/>
     </werkgevers>
</node>

为了使用XSLT转换为html,我有:

    <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:m="http://www.example.com/"
    exclude-result-prefixes="xs"
    version="2.0">

<xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
  <html>
  <body>

 <h2><xsl:value-of select="node/cv/naam"/></h2>

  <xsl:if test="node/werkgevers">
  <table border="1">
     <tr bgcolor="#9acd32">
      <th>Werkgevers</th>
      <th></th>
      <th></th>
      <th></th>
    </tr>

    <xsl:for-each select="node/werkgevers">
    <tr>
      <td>>></td>
      <td><xsl:value-of select="periode"/></td>
      <td><xsl:value-of select="naam"/></td>
      <td><xsl:value-of select="functie"/></td>
    </tr>
    </xsl:for-each>
  </table>
  </xsl:if>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

目前我将第一个和第二个XML与字符串操作结合起来,这是我认为不是一个很好的解决方案。我尝试了几个PHP代码,但无法解决它。

目前我现在将1 xml与1 xslt合并,并使用以下代码运行良好。

  // Load the XML source
  $xml_cv = new DOMDocument;
  $xml_cv->load($file_xml_total);

  // Load the XLS
  $xsl_cv = new DOMDocument;
  $xsl_cv->load($file_xsl_cv);

  // Configure the transformer
  $proc = new XSLTProcessor;
  $proc->importStyleSheet($xsl_cv); // attach the xsl rules
  $proc->transformToURI($xml_cv, $file_html_cv);

所以问题是:

1)如何将更多XML文件合并为1个XML文件,以便我可以使用与上述相同的PHP代码?

2)另一种解决方案可能是利用XMLT 2.0文档功能将不同的XML通过1 xslt组合在一起,但由于文件的名称是动态的,我找不到任何解决方法。其中一个答案是: XSLT: Merging two log files with different structure and time-representation

但是在这里有固定名称,如下所述:

<!-- The source-documents. -->
<xsl:variable name="doc1" select="doc('log1.xml')"/>
<xsl:variable name="doc2" select="doc('log2.xml')"/>

如何解决第二种方法?

基于新输入的开发

我有点迷失......基于新的输入我调查了它,并且遇到了相同的结果我遇到了麻烦。几个小时后,看起来处理

$proc->transformToXML

没有工作,所以我继续让它变得更加简单。所以现在经过几个小时我有以下非常简单的方法:

代码:

  $file_xsl_merge = 'C:\www\arlande.nl\sites\default\files\node_export\merge.xsl';
  $xsl = new DOMDocument('1.0', 'UTF-8');
  $xsl->load($file_xsl_merge);
  writetolog ("Dump of xslt: ". $xsl->savexml());

  $initXML = '<?xml version="1.0" encoding="UTF-8"?><node><dummy>33</dummy></node>';
  $xml = new DOMDocument('1.0', 'UTF-8');
  $xml->LoadXML ($initXML);
  writetolog ("Dump of XML: ". $xml->savexml());

  // TRANSFORM XML
  $proc = new XSLTProcessor;
  $proc->importStyleSheet($xsl);
  $newXML = $proc->transformToXML($xml,$file_xml_total);
  writetolog ("A dump of xml after processing is: ". $xml->savexml());
  writetolog ("String newXML is : ". $newXML);
  writetolog( "All XML should be combine now in file : " . $file_xml_total);

merge.xls:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

     <!-- The source-documents. -->
    <xsl:variable name="doc1" select="document('C:\www\arlande.nl\sites\default\files\node_export\cv.xml')"/>
    <xsl:variable name="doc2" select="document('C:\www\arlande.nl\sites\default\files\node_export\werkgevers.xml')"/>
    <xsl:variable name="doc3" select="document('C:\www\arlande.nl\sites\default\files\node_export\opleiding.xml')"/>
    <xsl:variable name="doc4" select="document('C:\www\arlande.nl\sites\default\files\node_export\opdracht_b.xml')"/>
    <xsl:variable name="doc5" select="document('C:\www\arlande.nl\sites\default\files\node_export\opdracht_s.xml')"/>

    <xsl:template match="node">
        <xsl:copy>
            <xsl:copy-of select="*"/>
            <xsl:copy-of select="$doc1/node/*"/>
            <xsl:copy-of select="$doc2/node/*"/>
            <xsl:copy-of select="$doc3/node/*"/>
            <xsl:copy-of select="$doc4/node/*"/>
            <xsl:copy-of select="$doc5/node/*"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

我从这段代码创建了一个日志文件,显示了:

16:22:00 Start run
16:22:00 s:1186:"Dump of xslt: <?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

     <!-- The source-documents. -->
    <xsl:variable name="doc1" select="document('C:\www\arlande.nl\sites\default\files\node_export\cv.xml')"/>
    <xsl:variable name="doc2" select="document('C:\www\arlande.nl\sites\default\files\node_export\werkgevers.xml')"/>
    <xsl:variable name="doc3" select="document('C:\www\arlande.nl\sites\default\files\node_export\opleiding.xml')"/>
    <xsl:variable name="doc4" select="document('C:\www\arlande.nl\sites\default\files\node_export\opdracht_b.xml')"/>
    <xsl:variable name="doc5" select="document('C:\www\arlande.nl\sites\default\files\node_export\opdracht_s.xml')"/>

    <xsl:template match="node">
        <xsl:copy>
            <xsl:copy-of select="*"/>
            <xsl:copy-of select="$doc1/node/*"/>
            <xsl:copy-of select="$doc2/node/*"/>
            <xsl:copy-of select="$doc3/node/*"/>
            <xsl:copy-of select="$doc4/node/*"/>
            <xsl:copy-of select="$doc5/node/*"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
";
16:22:00 s:83:"Dump of XML: <?xml version="1.0" encoding="UTF-8"?>
<node><dummy>33</dummy></node>
";
16:22:00 s:105:"A dump of xml after processing is: <?xml version="1.0" encoding="UTF-8"?>
<node><dummy>33</dummy></node>
";
16:22:00 s:19:"String newXML is : ";
16:22:00 s:108:"All XML should be combine now in file : C:/www/arlande.nl/sites/default/files/node_export/node_584_total.xml";

因此xslt中文档函数的处理再次无效......

  1. 我在搜索匹配/节点中尝试了几种组合。
  2. 所有单独的XML文件都在那里,所有文件都以...开头
  3. 有任何建议如何让这个工作?

2 个答案:

答案 0 :(得分:1)

变体1:使用XPath 1.0文档()

实际上,XSLT 1.0支持[[{{{Image|}}}|options|caption]]来加载其他XML文档。 (document())名称可以是半动态的。您可以使用主XML上的表达式来计算它。但它不能使用循环中的值。

变体2:在PHP中合并XML

要在PHP中合并XML文档,您需要定义外部框架并复制节点。

<xsl:variable name="doc1" select="document('log1.xml')"/>

输出:

$xmls = [
  'one.xml' => '<one/>',
  'three.xml' => '<two/>',
  'two.xml' => '<three/>'
];

$target = new DOMDocument();
$target->appendChild($target->createElement('files'));
foreach ($xmls as $fileName => $content) {
  $fileNode = $target
     ->documentElement
     ->appendChild($target->createElement('file'));
  $fileNode->setAttribute('name', $fileName);

  $source= new DOMDocument();
  $source->loadXml($content);
  $fileNode->appendChild(
    $target->importNode($source->documentElement, TRUE)
 );
} 

$target->formatOutput = TRUE;
echo $target->saveXml();

该示例使用字符串使其自包含。将其调整为文件意味着使用<?xml version="1.0"?> <files> <file name="one.xml"> <one/> </file> <file name="three.xml"> <two/> </file> <file name="two.xml"> <three/> </file> </files>

变体3:使用PHP回调来加载文档

Last PHP允许使用XSLT的回调。它们需要使用$source->load($fileName);进行注册。与eXSLT一起,您可以定义一个可以在循环中使用的函数。

XsltProcessor::registerPHPFunctions()

PHP函数:

<?xml version="1.0"?>
<xsl:stylesheet
  version="1.0"
  xmlns="http://www.w3.org/1999/xhtml/"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:php="http://php.net/xsl"
  xmlns:func="http://exslt.org/functions"
  xmlns:cxr="urn:your-function-namespace"
  extension-element-prefixes="php func"
  exclude-result-prefixes="#default cxr">

<func:function name="cxr:load-document">
  <xsl:param name="url"/>
  <func:result select="php:function('\YourNameSpace\XsltCallback::loadDocument', $url)"/>
</func:function>

</xsl:stylesheet>

答案 1 :(得分:0)

考虑使用带有XSLT的temp.xml文件。组合多个XML文件时,需要先阅读第一个XML,然后再使用document()

$file_xml_cv = '<?xml version="1.0" encoding="UTF-8"?>
                <node>
                  <cv>
                    <cvid>584</cvid>
                    <titel>Dit is een test cv</titel>
                    <naam>DHR H.V.H. Dagobert Duck</naam>
                  </cv>
                </node>';

$file_xml_werkgevers = '<?xml version="1.0" encoding="UTF-8"?>
                        <node>
                          <werkgevers>
                            <naam>Company 1</naam>
                            <Functie>Projectmanager en Informatie analist</Functie>
                            <periode>1967-01-01 00:00:00</periode>
                            <einddatum>1967-01-01 00:00:00</einddatum>
                          </werkgevers>
                          <werkgevers>
                            <naam>Company 2</naam>
                            <Functie>Systeemontwerper</Functie>
                            <periode/>
                            <einddatum/>
                          </werkgevers>
                        </node>';

// LOAD XML SOURCE
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->loadXML($file_xml_cv);

/// LOAD XSLT 
$xsl = new DOMDocument('1.0', 'UTF-8');
file_put_contents($cd.'/temp.xml', $file_xml_werkgevers);   // OUTPUT TEMP FILE

$xslstr ='<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
            <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
            <xsl:strip-space elements="*"/>

            <xsl:template match="node">
                <xsl:copy>
                    <xsl:copy-of select="*"/>
                    <xsl:copy-of select="document(\'temp.xml\')/node/*"/>
                </xsl:copy>
            </xsl:template>

           </xsl:stylesheet>';
$xsl->loadXML($xslstr);

// TRANSFORM XML
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
$newXML = $proc->transformToXML($xml);
unlink ($cd.'/temp.xml');                                 // DELETE TEMP FILE

echo $newXML;

# <?xml version="1.0" encoding="UTF-8"?>
# <node>
#   <cv>
#     <cvid>584</cvid>
#     <titel>Dit is een test cv</titel>
#     <naam>DHR H.V.H. Dagobert Duck</naam>
#   </cv>
#   <werkgevers>
#     <naam>Company 1</naam>
#     <Functie>Projectmanager en Informatie analist</Functie>
#     <periode>1967-01-01 00:00:00</periode>
#     <einddatum>1967-01-01 00:00:00</einddatum>
#   </werkgevers>
#   <werkgevers>
#     <naam>Company 2</naam>
#     <Functie>Systeemontwerper</Functie>
#     <periode/>
#     <einddatum/>
#   </werkgevers>
# </node>

您甚至可以在循环中为所有8个XML文件运行转换。下面用$file_xml_werkgevers三次迭代。使用最终结果进行html转换。

// LOAD XML SOURCE
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->loadXML($file_xml_cv);

foreach(array($file_xml_werkgevers, $file_xml_werkgevers, $file_xml_werkgevers) as $temp){
    $xsl = new DOMDocument('1.0', 'UTF-8');
    file_put_contents($cd.'/temp.xml', $temp);   // OUTPUT TO TEMP FILE

    $xslstr ='<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
                <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
                <xsl:strip-space elements="*"/>

                <xsl:template match="node">
                    <xsl:copy>
                        <xsl:copy-of select="*"/>
                        <xsl:copy-of select="document(\'temp.xml\')/node/*"/>
                    </xsl:copy>
                </xsl:template>

               </xsl:stylesheet>';
    $xsl->loadXML($xslstr);

    // TRANSFORM XML
    $proc = new XSLTProcessor;
    $proc->importStyleSheet($xsl);
    $newXML = $proc->transformToXML($xml);
    $xml->loadXML($newXML);

    unlink ($cd.'/temp.xml');                                 // DELETE TEMP FILE
}

echo $newXML;

# <?xml version="1.0" encoding="UTF-8"?>
# <node>
#   <cv>
#     <cvid>584</cvid>
#     <titel>Dit is een test cv</titel>
#     <naam>DHR H.V.H. Dagobert Duck</naam>
#   </cv>
#   <werkgevers>
#     <naam>Company 1</naam>
#     <Functie>Projectmanager en Informatie analist</Functie>
#     <periode>1967-01-01 00:00:00</periode>
#     <einddatum>1967-01-01 00:00:00</einddatum>
#   </werkgevers>
#   <werkgevers>
#     <naam>Company 2</naam>
#     <Functie>Systeemontwerper</Functie>
#     <periode/>
#     <einddatum/>
#   </werkgevers>
#   <werkgevers>
#     <naam>Company 1</naam>
#     <Functie>Projectmanager en Informatie analist</Functie>
#     <periode>1967-01-01 00:00:00</periode>
#     <einddatum>1967-01-01 00:00:00</einddatum>
#   </werkgevers>
#   <werkgevers>
#     <naam>Company 2</naam>
#     <Functie>Systeemontwerper</Functie>
#     <periode/>
#     <einddatum/>
#   </werkgevers>
#   <werkgevers>
#     <naam>Company 1</naam>
#     <Functie>Projectmanager en Informatie analist</Functie>
#     <periode>1967-01-01 00:00:00</periode>
#     <einddatum>1967-01-01 00:00:00</einddatum>
#   </werkgevers>
#   <werkgevers>
#     <naam>Company 2</naam>
#     <Functie>Systeemontwerper</Functie>
#     <periode/>
#     <einddatum/>
#   </werkgevers>
# </node>