(XML)PHP没有重命名所有标签?

时间:2017-01-02 21:43:38

标签: php xml

我遇到了问题...我想重命名某些XML文件中的标签。它适用于此代码:

$xml = file_get_contents('data/onlinekeystore.xml');
renameTags($xml, 'priceEUR', 'price', 'data/onlinekeystore.xml');

但是如果我想重命名另一个XML文件,它就不能使用SAME方法...... 请参阅下面的示例。我不知道为什么... 有没有人有想法可以帮助我?

$xml = file_get_contents('data/g2a.xml');
renameTags($xml, 'name', 'title', 'data/g2a.xml');

功能代码:

function renameTags($xml, $old, $new, $path){
    $dom = new DOMDocument();
    $dom->loadXML($xml);

    $nodes = $dom->getElementsByTagName($old);
    $toRemove = array();
    foreach ($nodes as $node) {
        $newNode = $dom->createElement($new);
        foreach ($node->attributes as $attribute) {
            $newNode->setAttribute($attribute->name, $attribute->value);
        }

        foreach ($node->childNodes as $child) {
            $newNode->appendChild($node->removeChild($child));
        }

        $node->parentNode->appendChild($newNode);
        $toRemove[] = $node;
    }

    foreach ($toRemove as $node) {
        $node->parentNode->removeChild($node);
    }

    $dom->saveXML();
    $dom->save($path);
}

onlinekeystore.xml输入:

<product>
    <priceEUR>5.95</priceEUR>
</product>

onlinekeystore.xml输出:

<product>
   <price>5.95</price>
</product>

g2a.xml输入:

<products>
    <name><![CDATA[1 Random STEAM PREMIUM CD-KEY]]></name>
</products>

g2a.xml输出:

<products>
    <name><![CDATA[1 Random STEAM PREMIUM CD-KEY]]></name>
</products>

问候

1 个答案:

答案 0 :(得分:0)

考虑运行XSLT的动态Identity Transform,然后在文档中的任何位置更新特定模板中的节点名称。 sprintf格式化传入$old$new值的XSL字符串。这个过程避免了整个树的任何嵌套循环,甚至无论输入格式如何都能输出漂亮的输出。

function renameTags($xml, $old, $new, $path){
    // LOAD XML 
    $dom = new DOMDocument();
    $dom->loadXML($xml);

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

      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>

      <xsl:template match="%1$s">
        <xsl:element name="%2$s">            
          <xsl:apply-templates/>
        </xsl:element>
      </xsl:template>

    </xsl:transform>';
    $xsl  = new DOMDocument();
    $xsl->loadXML(sprintf($xslstr, $old, $new));

    // INITIALIZE TRANSFORMER (REQUIRES php_xsl EXTENSION ENABLED IN .ini)
    $proc = new XSLTProcessor;
    $proc->importStyleSheet($xsl); 

    // TRANSFORM XML AND SAVE OUTPUT
    $newXML = $proc->transformToXML($dom);
    file_put_contents($path, $newXML);
}

<强>输出

renameTags('<product><priceEUR>5.95</priceEUR></product>', 'priceEUR', 'price', 'data/onlinekeystore.xml');

// <?xml version="1.0" encoding="UTF-8"?>
// <product>
//   <price><![CDATA[5.95]]></price>
// </product>    

renameTags('<products><name><![CDATA[1 Random STEAM PREMIUM CD-KEY]]></name></products>', 'name', 'title', 'data/g2a.xml');

// <?xml version="1.0" encoding="UTF-8"?>
// <products>
//   <title><![CDATA[1 Random STEAM PREMIUM CD-KEY]]></title>
// </products>

注意: 在XSLT中,除非<![CDATA[...]]中明确指定,否则不会保留<xsl:output>标记。现在,任何新节点的文本都包含它。删除输出规范,没有CData标记渲染。因此要么为所有人都包含这样的转义标签,要么没有。