doutuoji8418 2017-01-02 21:43
浏览 46
已采纳

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

I have a problem... I want to rename the tags in some XML files. An it works with this code:

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

But if I want to rename another XML file it doens't work with the SAME method... See the example below. I have no idea why... Does anybody has an idea and can help me?

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

Function Code:

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

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

onlinekeystore.xml Ouput:

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

g2a.xml Input:

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

g2a.xml Ouput:

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

Greetings

  • 写回答

1条回答 默认 最新

  • douping1993 2017-01-03 01:40
    关注

    Consider a dynamic XSLT running the Identity Transform and then updates node names in a specific template anywhere in document. The sprintf formats XSL string passing in $old and $new values. This process avoids any nested looping through entire tree and even pretty prints output no matter the format of input.

    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);
    }
    

    Output

    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>
    

    Note: In XSLT, the <![CDATA[...]] tags are not preserved unless explicitly specified in <xsl:output>. Right now, any new node's text is wrapped with it. Remove the output spec and no CData tags render. So either include such escape tags for all or none.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上