【问题标题】:update xml file with php Xpath使用 php Xpath 更新 xml 文件
【发布时间】:2011-05-29 05:26:53
【问题描述】:

如何使用使用 Xpath (php) 更新文件? 我的文件结构:

<?xml version="1.0" encoding="ISO-8859-1"?>
<PersonList>
  <Person>
    <Name>Sonu Kapoor</Name>
    <Age>24</Age>
    <Gender>M</Gender>
    <PostalCode>54879</PostalCode>
  </Person>
  <Person>
    <Name>Jasmin</Name>
    <Age>28</Age>
    <Gender>F</Gender>
    <PostalCode>78745</PostalCode>
  </Person>
   <Person>
    <Name>Josef</Name>
    <Age>232</Age>
    <Gender>F</Gender>
    <PostalCode>53454</PostalCode>
  </Person>
</PersonList>

我需要更改名称为“Jasmin”的年龄和性别值。我尝试使用谷歌,但没有找到任何好东西:(

【问题讨论】:

    标签: php xml xslt xpath


    【解决方案1】:

    你可以试试simplexml

    $xml = simplexml_load_string($str);
    $obj = $xml->xpath('//Person[Name="Jasmin"]');
    $obj[0]->Age = 30;
    $obj[0]->Gender = 'M';
    echo $xml->asXml();
    
    /* or */ 
    $xml->asXml($filename); <-- save xml into file
    

    【讨论】:

      【解决方案2】:

      如何使用使用 Xpath (php) 更新 文件?

      XPath 是一种用于 XML 文档的查询语言。因此,XPath 表达式不能修改 XML 文档——它只能从中选择节点或其他数据

      一个修改过的 XML 文档可以在托管 XPath 引擎的编程语言的帮助下生成——这可能是 XSLT、C#、Java、PHP,...

      我需要更改年龄值和 姓名为“Jasmin”的性别。

      这是一个简单的 XSLT 转换,它根据这些要求生成一个新的 XML 文档

      <xsl:stylesheet version="1.0"
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
       xmlns:my="my:my" exclude-result-prefixes="my">
       <xsl:output omit-xml-declaration="yes" indent="yes"/>
       <xsl:strip-space elements="*"/>
      
       <my:params>
        <name>Jasmin</name>
        <age>31</age>
        <gender>X</gender>
       </my:params>
      
       <xsl:variable name="vParams" select=
       "document('')/*/my:params"/>
      
       <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
       </xsl:template>
      
       <xsl:template match=
        "Person[Name=document('')/*/my:params/name]/Age">
        <Age><xsl:value-of select="$vParams/age"/></Age>
       </xsl:template>
      
       <xsl:template match=
        "Person[Name=document('')/*/my:params/name]/Gender">
        <Gender><xsl:value-of select="$vParams/gender"/></Gender>
       </xsl:template>
      </xsl:stylesheet>
      

      当此转换应用于提供的 XML 文档时

      <PersonList>
          <Person>
              <Name>Sonu Kapoor</Name>
              <Age>24</Age>
              <Gender>M</Gender>
              <PostalCode>54879</PostalCode>
          </Person>
          <Person>
              <Name>Jasmin</Name>
              <Age>28</Age>
              <Gender>F</Gender>
              <PostalCode>78745</PostalCode>
          </Person>
          <Person>
              <Name>Josef</Name>
              <Age>232</Age>
              <Gender>F</Gender>
              <PostalCode>53454</PostalCode>
          </Person>
      </PersonList>
      

      产生想要的正确结果

      <PersonList>
         <Person>
            <Name>Sonu Kapoor</Name>
            <Age>24</Age>
            <Gender>M</Gender>
            <PostalCode>54879</PostalCode>
         </Person>
         <Person>
            <Name>Jasmin</Name>
            <Age>31</Age>
            <Gender>X</Gender>
            <PostalCode>78745</PostalCode>
         </Person>
         <Person>
            <Name>Josef</Name>
            <Age>232</Age>
            <Gender>F</Gender>
            <PostalCode>53454</PostalCode>
         </Person>
      </PersonList>
      

      【讨论】:

      • "因此,只有 XPath 表达式不能修改 XML 文档..." 嗯,错字?
      • @CaptainHypertext 感谢您注意到这一点。现已更正。
      【解决方案3】:

      您可以使用 PHP 中的 DOMDocument。

      您加载您的文件,然后通过文档的 childNodes 循环。

      <?php
      $dom=new DOMDocument();
      $dom->load("file.xml");
      
      $root=$dom->documentElement; // This can differ (I am not sure, it can be only documentElement or documentElement->firstChild or only firstChild)
      
      $nodesToDelete=array();
      
      $markers=$root->getElementsByTagName('marker');
      
      // Loop trough childNodes
      foreach ($markers as $marker) {
          $type=$marker->getElementsByTagName('type')->item(0)->textContent;
          $title=$marker->getElementsByTagName('title')->item(0)->textContent;
          $address=$marker->getElementsByTagName('address')->item(0)->textContent;
          $latitude=$marker->getElementsByTagName('latitude')->item(0)->textContent;
          $longitude=$marker->getElementsByTagName('longitude')->item(0)->textContent;
      
          // Your filters here
      
          // To remove the marker you just add it to a list of nodes to delete
          $nodesToDelete[]=$marker;
      }
      
      // You delete the nodes
      foreach ($nodesToDelete as $node) $node->parentNode->removeChild($node);
      
      echo $dom->saveXML();
      ?>
      

      你可以像这样保存你的输出 XML

      $dom->saveXML(); // This will return the XML as a string
      $dom->save('file.xml'); // This saves the XML to a file
      

      要在 JavaScript 中进行这种解析,您应该使用 jQuery(一个小而强大的库)。

      您可以直接从 Google 代码库中包含该库。

      <script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
      

      该库是跨浏览器的,而且非常小。它在很多情况下应该被缓存,因为一些网站使用它来自谷歌代码

      $(yourXMLStringOrDocument).find("marker").each(function () {
           var marker=$(this);
      
           var type=marker.find('type').text();
           var title=marker.find('title').text();
           var address=marker.find('address').text();
           var latitude=marker.find('latitude').text();
           var longitude=marker.find('longitude').text();
      });
      

      【讨论】:

        【解决方案4】:

        我知道,我迟到了。下面是一个基于纯 DOMXPath 的解决方案:

        <?php
        $content = <<<XML
        <?xml version="1.0" encoding="ISO-8859-1"?>
        <PersonList>
          <Person>
            <Name>Sonu Kapoor</Name>
            <Age>24</Age>
            <Gender>M</Gender>
            <PostalCode>54879</PostalCode>
          </Person>
          <Person>
            <Name>Jasmin</Name>
            <Age>28</Age>
            <Gender>M</Gender>
            <PostalCode>78745</PostalCode>
          </Person>
           <Person>
            <Name>Josef</Name>
            <Age>232</Age>
            <Gender>F</Gender>
            <PostalCode>53454</PostalCode>
          </Person>
        </PersonList>
        XML;
        
        $doc = new DOMDocument();
        $doc->loadXML($content);
        $xp = new DOMXPath($doc);
        $nodeList = $xp->query('/PersonList/Person[./Name="Jasmin"]/*');
        for($i = 0; $i < $nodeList->length; $i++) {
            switch ($nodeList->item($i)->nodeName) {
                case 'Age':
                    $nodeList->item($i)->nodeValue = 33;
                    break;
                case 'Gender':
                    $nodeList->item($i)->nodeValue = 'F';
                    break;
            }
        }
        $doc->formatOutput = true;
        echo $doc->saveXML();
        

        http://3v4l.org/kqjoj

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-09-15
          • 2014-05-31
          • 2015-11-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多