drmticpet66231422 2012-12-02 22:42
浏览 146
已采纳

从兄弟节点到匹配的节点检索数据

I'm iterating through a xml doc with SimpleXML. I have an array ($ids) with id's and I'm checking whether there's a match or not in the XML (Worksheet/Table/Row/Cell/Data). If it's a match I want to be able to get to the data from the following two siblings, but I can't figure out how.

from the php:

// $ids <---- array('8', '53', '38')

foreach ($thePositions->Worksheet->Table->Row as $row) {

    if($row->Cell->Data == true) {

        for ($i = 0; $i < count($ids); $i++) {
            foreach($row->Cell->Data as $data) {

                if ($data == $ids[$i]) {
                    echo 'match!';

                    /* 
                       Tried $siblings = $data->xpath('preceding-sibling::* | following-sibling::*');
                       but doesn't seem to work in this case.
                    */
                }
            }
        }
    }
}

the xml:

<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:o="urn:schemas-microsoft-com:office:office"
 xmlns:x="urn:schemas-microsoft-com:office:excel"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:html="http://www.w3.org/TR/REC-html40">
 <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
  <LastAuthor>Herpa Derp </LastAuthor>
  <Created>2012-09-25T13:44:01Z</Created>
  <LastSaved>2012-09-25T13:48:24Z</LastSaved>
  <Version>14.0</Version>
 </DocumentProperties>
 <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
  <AllowPNG/>
 </OfficeDocumentSettings>
 <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
  <WindowHeight>14060</WindowHeight>
  <WindowWidth>25040</WindowWidth>
  <WindowTopX>25540</WindowTopX>
  <WindowTopY>4100</WindowTopY>
  <Date1904/>
  <ProtectStructure>False</ProtectStructure>
  <ProtectWindows>False</ProtectWindows>
 </ExcelWorkbook>
 <Styles>
  <Style ss:ID="Default" ss:Name="Normal">
   <Alignment ss:Vertical="Bottom"/>
   <Borders/>
   <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#000000"/>
   <Interior/>
   <NumberFormat/>
   <Protection/>
  </Style>
  <Style ss:ID="s62">
   <Font ss:FontName="Courier" ss:Color="#000000"/>
  </Style>
 </Styles>
 <Worksheet ss:Name="Workbook1.csv">
  <Table ss:ExpandedColumnCount="5" ss:ExpandedRowCount="79" x:FullColumns="1"
   x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="15">
   <Column ss:Index="2" ss:AutoFitWidth="0" ss:Width="43"/>
   <Column ss:AutoFitWidth="0" ss:Width="113"/>
   <Column ss:Index="5" ss:AutoFitWidth="0" ss:Width="220"/>
   <Row ss:Index="6">
    <Cell ss:Index="3" ss:StyleID="s62"/>
   </Row>
   <Row>
    <Cell ss:Index="3" ss:StyleID="s62"/>
   </Row>
   <Row>
    <Cell ss:Index="3" ss:StyleID="s62"/>
   </Row>
   <Row>
    <Cell ss:Index="2"><Data ss:Type="String">id</Data></Cell>
    <Cell ss:StyleID="s62"><Data ss:Type="String">latitude</Data></Cell>
    <Cell><Data ss:Type="String">longitude</Data></Cell>
   </Row>
   <Row>
    <Cell ss:Index="2"><Data ss:Type="Number">8</Data></Cell>
    <Cell ss:StyleID="s62"><Data ss:Type="Number">57.4999</Data></Cell>    // to be saved to $latutude
    <Cell><Data ss:Type="Number">15.8280</Data></Cell>    // to be saved to $longitude
   </Row>
   <Row>
    <Cell ss:Index="2"><Data ss:Type="Number">38</Data></Cell>
    <Cell><Data ss:Type="Number">56.5659</Data></Cell>
    <Cell><Data ss:Type="Number">16.1380</Data></Cell>
   </Row>
  • 写回答

4条回答 默认 最新

  • doulao2916 2012-12-05 00:00
    关注

    The reason asking for siblings isn't working is that the <Data> elements aren't siblings; they're more like cousins - children of adjacent <Cell> elements.

    For the same reason, you shouldn't be using foreach($row->Cell->Data as $data), as this is equivalent to foreach($row->Cell[0]->Data as $data), i.e. look at all <Data> children of the first <Cell> node. Since there will only ever be one <Data> element in a <Cell>, you might as well just write $data = $row->Cell[0]->Data - which in this case is fine, because the values you're looking for are at the beginning of rows.

    What you actually need to do is loop over the <Cell>s: foreach($row->Cell as $cell) { $data = $cell->Data; /* ... */ }

    You then have a couple of options for finding the adjacent cells, including XPath. A more "PHP-ish" way would be to use array indexes (siblings are indexed numerically in SimpleXML loop/array access):

    foreach($row->Cell as $cell_index => $cell)
    {
        $data = $cell->Data;
        if ($data == $ids[$i])
        {
            // Tip: always cast SimpleXML objects to string when you're done with their magic XMLiness
            $latitudes[$i] = (string)$row->Cell[ $cell_index + 1 ]->Data;
            $longitudes[$i] = (string)$row->Cell[ $cell_index + 2 ]->Data;
        }
    }
    

    Alternatively, you could rely on your IDs always being in the first column, and the lat and long in the next two (this is a spreadsheet, after all!) and avoid the inner loop altogether:

    if ( $row->Cell[0]->Data == $ids[$i] )
    {
        $latitudes[$i] = (string)$row->Cell[1]->Data;
        $longitudes[$i] = (string)$row->Cell[2]->Data;
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?
  • ¥15 乘性高斯噪声在深度学习网络中的应用
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛