PHP,XML,回显时重复属性的问题

时间:2011-12-08 07:16:32

标签: php xml html-table structure

我得到了一个由PHP回应的XML文件,并且所有代码都运行良好但我的问题是在标签内部(考试和属性是正在回应的章节)有多个标签(例如,那是什么被作为考试#)回应,我正在将数据回显到一个表格,我希望它像这样显示:

  
     

|第1章|第2章|

     

| - 考试1 --- | - 考试1 --- |

     

| --Exam 2 --- | --Exam 2 --- |

     

|第3章|第4章|

     

| - 考试1 --- | - 考试1 --- |

     

但我得到的是这样的:(我知道为什么)

  
     

|第1章|

     

| --Exam 1 --- |

     

|第1章|

     

| --Exam 2 --- |

     

|第2章|

     

| --Exam 1 --- |

     

它不断重复标记的属性,我知道原因,因为我正在回显我在表数据中作为变量的标记属性。所以问题不在于它为什么会发生,而是如何改变它以我想要的方式显示它。

我想也许有一种方法可以删除属性,如果有多个(我知道你可以删除它但我不知道如何显示它并删除其他属性)

我拥有的代码是这样的:

以XML格式

<maintag>
  <exam chapter="Chapter 1">
    <ex id="1">Exam 1</ex>
    <ex id="2">Exam 2</ex>
    <ex id="3">Exam 3</ex>
  </exam>

  <exam chapter="Chapter 2">
    <ex id="4">Exam 1</ex>
    <ex id="5">Exam 2</ex>
  </exam>

  <exam chapter="Chapter 3">
    <ex id="6">Exam 1</ex>
  </exam>

  <exam chapter="Chapter 4">
    <ex id="7">Exam 1</ex>
    <ex id="8">Exam 2</ex>
    <ex id="9">Exam 3</ex>
    <ex id="10">Exam 4</ex>
  </exam>
</maintag>


PHP

<?php
$xml = DOMDocument::load('examdata.xml');
$xpath = new DOMXPath($xml);
$exams = $xpath->query('//exam/ex');

$istyle = 1; //This is to add gray after every other row

echo "      <table cellpadding=\"0\" cellspacing=\"3\" border=\"0\" width=\"60%\" align=\"center\">
            <tr id=\"center\" bgcolor=\"#999\">
                <td>Book</td>
                <td>Exam</td>
                <td>ID</td>
                <td>Student's Exam Status</td>
            </tr>
";

foreach($exams as $exams2) {
    $chapter = $exams2->parentNode->getAttribute('chapter');
    $examid = $exams2->getAttribute('id');
    $examname = $exams2->nodeValue;

    if ($examid < 5) { //where it says 5 there goes a php variable where it has the queried user's exam number from the database, again this is all finished no need to change this.
        $exstatus = "You already took this exam.";
    }elseif ($examid == 5) {
        $exstatus = "This is your exam (exam link)";
    }elseif ($examid > 5) {
        $exstatus = "You are not yet on this exam";
    }

echo "<tr id=\"center\"";

        if ($istyle % 2 == 0)
            echo " bgcolor=\"#ccc\"";

        echo ">
                <td>$chapter</td>
                <td>$examname</td>
                <td>$examid</td>
                <td>$exstatus</td>
            </tr>";

            $istyle++;
}

echo "
        </table>";
?>

请注意,表格结构与我说的我想要的方式不同,而且我已经将它上面了,我只是改变了它,因为我不能按原样保留它。

请注意,我想要更改的内容是它所说的章节,我希望它一次显示在它下面以显示考试1及其下面的考试等。本章旁边是下一章(本例中为第2章),下面是考试1及以下考试2等。然后在考试2下面创建另一个表格行,并在其他两个章节之下放置其他考试。

请注意,考试不遵循模式,这是该文件的编辑版本,因为有数百个,并且这些值与您在上面看到的不同。

上面的代码有效,我只想修改它以满足我的要求。

2 个答案:

答案 0 :(得分:1)

我已经明白了,我花了好几个小时,但我终于做到了。

这是我用于PHP的代码,XML保持不变。我将尝试尽可能详细,以便它可以帮助任何有类似问题的人,或者他们可以从中提取信息并根据他们的需要进行修改。

<?php
//self explanatory
$xml = DOMDocument::load('examdata.xml');
//again, self explanatory
$xpath = new DOMXPath($xml);
//looks for ex under exam in the xml I loaded above xml
$exams = $xpath->query('//exam/ex');
//I just put a number for testing purposes but it actually gets the user's exam id from the database
$studentexnum = "5";
//column counter, will be used to tell that after every 2 chapters, break the table data (td) and table row (tr) and create a new one
$_2chapters = 1;
//Opens the table and displays it to the client
echo "<table cellpadding=\"5\" cellspacing=\"5\" border=\"0\" width=\"25%\" align=\"center\">
    <tr>"; //Opens the first table row and end the echoing

//starts the loop, for every exam, makes exam2 same as exam
foreach($exams as $exams2) {
//looks at my xml file for the tag ex (what I defined above) and gets the attribute called chapter from his parent (the tag above it)
    $chapter = $exams2->parentNode->getAttribute('chapter');
//gets the attribute called id from the tag ex
    $examid = $exams2->getAttribute('id');
//makes the tag ex a string so we could display it
    $examname = $exams2->nodeValue;

////////////////////////////////////////Now for the Fun Part/////////////////////////////////////////////////////////////////////////////////

//conditional statement saying that if the variable chapter2 is set, display the conditions below, if it's not set (which is not when its starts the loop) do something else
    if (isset($chapter2)){
//says if variable chapter defined above is equal to variable chapter 2 which is defined below do something. This is not true the first time but it is the rest of the loop, even is is a million.
            if ($chapter == $chapter2) {
//variable chaptertd (which is called below) will equal to nothing if chapter equals to chapter2, this will happen at every exam (every ex tag in my xml file which is in the question above)
//this will avoid having repeated chapter, ie: chapter1 - exam one, chapter1 - exam 2, chapter1 exam 3, ect. will make it chapter 1, exam 1, exam 2, exam 3, ect
                $chaptertd = "";
//if chapter does not equal to chapter2
                }else {
//here we increment variable _2chapters that was 1 above, now is two, this is necessary so it could display two chapters side by side and break right before the third chapter, this will happen later
                $_2chapters++;
                $chapter2 = $chapter; //THIS PART IS EDITED, BUT NECESSARY
//Now we give a value to variable chaptertd, it was nothing before because I didn't want to repeat the title every time the loop found a new tag ex from my xml. This will only happen once in every chapter
                $chaptertd = "
        </td>
        <td align=\"center\" valign=\"top\">$chapter2";//here we create the html that variable chaptertd will be displaying after a new name from the attribute chapter is found. This will display the name of the chapter to our table
                }
//this else will only happen the first time the loop runs since only the first time is when the variable chapter2 is not defined, after this runs the variable chapter2 will have been defined
            }else {
//chapter2 will be the same as chapter, if chapter equals to the string chapter1 so will chapter2.
                $chapter2 = $chapter;
//here we create the same td as above since we want to display the name of the chapter the fist time it runs, if we don't do this the first chapter won't be display to the client
                $chaptertd = "
        <td align=\"center\" valign=\"top\">$chapter2";
            }
//This part you don't have to concern yourself with it, I made this because I needed it to display different info depending whether the user was allow to see that exam.
//the variable examval is defined outside this code, that's on my html code which would do nothing here since it uses javascript and css. this gets the attribute id from our ex tag.
    if ($examid < $studentexnum) {
        $exval = "lessthan";
    }elseif ($examid == 5) {
        $exval = "equalto";
    }elseif ($examid > 5) {
        $exval = "greaterthan";
    }

//here we say what happens when the variable _2chapters reaches the third attribute called chapter. we say if the remainder of variable _2chapters divided by 3 equals 0 do something
//else do nothing since we didn't define the else because we didn't needed it. this part will only happen at every third chapter, it will break from the previous chapter thus making
//it a new row right under the values of the tag ex which is under chapter 1 the third time the loops runs, but this will happen infinite amounts of time, after that it will be under
//chapter 3 and after that chapter 5 and so on.
            if ($_2chapters % 3 == 0) {
//here we reset the count back to one because if we don't and there's more than one tag ex under chapter 3, it will be braking after every ex
                $_2chapters = 1;
//here we echo the break from the previous chapter
            echo "
        </td>
    </tr>
    <tr id=\"center\">";
    }
//here we echo the variable chaptertd which we gave different values to above depending whether the chapter's name has been declared already or not. If it has been declared, chaptertd
//won't show anything, if the chapter has never been declared it will create a new td and display the chapter's name and after that it will become nothing again
echo "$chaptertd<br />
            <a href=\"#\" class=\"modalInput\" rel=\"#$exval\">$examname</a>";//here we show the client what's the name of the exams under the given chapter, there could be one or one hundred of this and it will only display the chapter once and will display the rest
//of the exam names one after the other

//here we say that chapter2 equals to chapter, this way chapter2 will equal to the name of that loop, if the next time it repeats there's a new chapter the value of chapter will change
//thus making this statement false above and that will force it to create a new td with the new name until another name appears.
            $chapter2 = $chapter;
}

//close the table to have a well formatted html file to display to the client.
echo "
        </td>
    </tr>
</table>";
?>

我实际上已经知道了,但是这个“智能论坛”不允许我在8小时之前回答我的OWN问题,因为我没有足够的积分或其他东西。这就好像它试图说,因为我是新来的,我是愚蠢的,无法在8小时内找到我自己的问题的解决方案。所以我去睡觉了。我只是想帮助将来可能会来这篇文章的其他人,希望答案能回答他们的一些问题。

答案 1 :(得分:0)

你可能意味着......

foreach($exams as $exam)

...从数组中获取一个项目,而不是......

foreach($exams as $exams)

BTW我会想到变量 exam ex 的其他名称,使用描述它们的名称,也许是考试和< EM>章