php - 从 sibling 中检索数据到匹配的节点

标签 php xml xpath simplexml siblings

我正在使用 SimpleXML 遍历 xml 文档。我有一个带有 id 的数组($ids),我正在检查 XML(工作表/表/行/单元格/数据)中是否存在匹配项。如果匹配,我希望能够从以下两个 sibling 那里获取数据,但我不知道如何做。

来自 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.
                    */
                }
            }
        }
    }
}

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>

最佳答案

请求 sibling 不起作用的原因是 <Data>元素不是 sibling ;他们更像是堂兄弟——相邻的 child <Cell>元素。

出于同样的原因,你不应该使用 foreach($row->Cell->Data as $data) ,因为这相当于 foreach($row->Cell[0]->Data as $data) ,即查看所有 <Data>第一个 child <Cell>节点。因为永远只有一个 <Data> <Cell> 中的元素, 你不妨写 $data = $row->Cell[0]->Data - 在这种情况下很好,因为您要查找的值位于行的开头。

您实际需要做的是遍历 <Cell>小号:foreach($row->Cell as $cell) { $data = $cell->Data; /* ... */ }

然后您可以使用几个选项来查找相邻的单元格,包括 XPath。一种更“PHP 风格”的方法是使用数组索引( sibling 在 SimpleXML 循环/数组访问中按数字索引):

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

或者,您可以依靠您的 ID 始终位于第一列,纬度和经度位于接下来的两列(毕竟这是一个电子表格!)并完全避免内部循环:

if ( $row->Cell[0]->Data == $ids[$i] )
{
    $latitudes[$i] = (string)$row->Cell[1]->Data;
    $longitudes[$i] = (string)$row->Cell[2]->Data;
}

关于php - 从 sibling 中检索数据到匹配的节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13674731/

相关文章:

php - Wordpress:previous_post_link/next_post_link 按字母顺序排列?

php - 安全地将 HTML 内容插入数据库表

android - 在 Android 中选择节点?

c# - XSLT 转换 : Updating nodes of output xml

php - 如何: persistent PHP session across subdomains

php - 如何在 wordpress 画廊弹出窗口中插入描述?

c# - Xamarin 安卓 C# : Using the xml resource folder and manifest to define an intent filter for detecting connected usb devices crashs application

xml - 如何将 xml 解析为 "messages"并使用流解析在 scala 中打印出来?

xml - XMLSchema 中复杂类型的联合

c# - 如何使用 XPath 选择带有引号字符的文本?