我想重新设计xml结构

时间:2011-03-21 17:58:49

标签: php mysql xml

我的情况是我无法编写代码请告诉我..

我想在xml中显示1个产品 - > 1类别 - >许多子类别如果类别改变那么1个产品 - >第二类 - > 2子类别等。产品总是1产品没有改变..

1个基于xml的产品。

请帮帮我......

以下是目前的结构:

<?
include_once("./inc/config.php");
include_once("jsAdminMethods.php");
$productID = $_POST['productID'];

//echo $productID;

$productQuery = mysql_query("select a.productId, a.productName, a.productAbout, a.productPic, aa.categoryID, aa.categoryName, aa.categoryDiscription,  aa.categoryPic, l.subCategoryID, l.subCategoryName, l.subCategoryDescription from category aa, product a, subCategory l where a.productID = aa.productID and l.categoryID = aa.categoryID and a.productID = $productID");
$num = mysql_num_rows($productQuery);

if(!$num == 0 ){
    $_fileName ="";

    $file= fopen("../xml/{$productID}.xml" , "w"); 


    $_xml ="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
    $_XML = "<!DOCTYPE Server SYSTEM \"opt/pdos/etc/pdoslrd.dtd\">";

    $_xml .="<cmm>";


     while ($row = mysql_fetch_array($productQuery, MYSQL_ASSOC)) { 

        $_xml .=" <product>";
        $_xml .="   <productID>" . $row['productId'] . "</productID>";
        $_xml .="   <productName><![CDATA[" . htmlspecialchars($row['productName'],ENT_QUOTES) . "]]></productName>";   
        $_xml .="   <productDescription><![CDATA[" . htmlspecialchars($row['productAbout'],ENT_QUOTES) . "]]></productDescription>";    
        $_xml .="   <productPicture><![CDATA[" . htmlspecialchars($row['productPic'],ENT_QUOTES) . "]]></productPicture>";
        $_xml .=" <category>";
        $_xml .="   <categoryID>" . $row['categoryID'] . "</categoryID>";
        $_xml .="   <categoryName><![CDATA[" . htmlspecialchars($row['categoryName'],ENT_QUOTES) . "]]></categoryName>";    
        $_xml .="   <categoryDescription><![CDATA[" . htmlspecialchars($row['categoryDiscription']) . "]]></categoryDescription>";  
        $_xml .="   <categoryPicture><![CDATA[" . htmlspecialchars($row['categoryPic'],ENT_QUOTES) . "]]></categoryPicture>";               
        $_xml .=" <subCategory>";
        $_xml .="   <subCategoryID>" . $row['subCategoryID'] . "</subCategoryID>";
        $_xml .="   <subCategoryName><![CDATA[" . htmlspecialchars($row['subCategoryName'],ENT_QUOTES) . "]]></subCategoryName>";   
        $_xml .="   <subCategoryDetail><![CDATA[" . htmlspecialchars($row['subCategoryDescription'],ENT_QUOTES) . "]]></subCategoryDetail>";                
        $_xml .=" </subCategory>";
        $_xml .=" </category>";
        $_xml .=" </product>";

    }
    $_xml .="</cmm>";
    fwrite($file, $_xml);
    fclose($file);


    $value = "product XML Generted Successfully";
    $tagproductXML = md5($value);
    header("location:xmlGenerator.php?tagproductXML=$tagproductXML");
}

else{
      echo "No Records found in xml";   
}

?>

2 个答案:

答案 0 :(得分:2)

文体提示,如果您使用的是PHP 5.3:

使用heredocs和匿名函数来保存所有那些可怕的字符串连接:

$x = function($txt) {
    return(htmlspecialchars($txt));
}

然后

while($row ...) {
   $_xml .= <<<EOL
<product>
   <productID>{$row['productID']}</productID>
   <productName>{$x($row['productName'])}</productName>
    etc...
EOL;
}

注意我是如何使用匿名函数$ x替换对htmlspecialchars()的直接调用,并在HEREDOC中使用它来在构建字符串时转义文本。使用这种类型的构造可以使您不必在一行又一行的字符串连接之后执行该行,从而减轻了必须在您正在构建的字符串中转义引号的负担,并且使用正确的语法高亮编辑器,远远不够比原版更容易阅读。

答案 1 :(得分:1)

我不确定我是否完全理解这个问题,但我会抓住它。

  

我想在xml中显示1个产品 - &gt; 1类别 - &gt;许多子类别如果类别改变那么1个产品 - &gt;第二类 - &gt; 2子类别等。产品总是1产品没有改变..

听起来你说的是一个产品可能属于多个类别。您希望<product>标记内的该产品类别(及其子类别)的全部

鉴于您的数据集只包含一个产品,这只需要对您的循环进行一些小的更改。

 $seen_first_row = false;
 while ($row = mysql_fetch_array($productQuery, MYSQL_ASSOC)) { 
    if(!$seen_first_row) {
        $seen_first_row = true;
        $_xml .=" <product>";
        $_xml .="   <productID>" . $row['productId'] . "</productID>";
        $_xml .="   <productName><![CDATA[" . $x($row['productName'],ENT_QUOTES) . "]]></productName>";   
        $_xml .="   <productDescription><![CDATA[" . $x($row['productAbout'],ENT_QUOTES) . "]]></productDescription>";    
        $_xml .="   <productPicture><![CDATA[" . $x($row['productPic'],ENT_QUOTES) . "]]></productPicture>";
    }
    // Category and Subcategory XML here
}
$_xml .=" </product></cmm>";

这里有两处变化。首先,一个新变量:$seen_first_row。当您开始从数据库中获取结果时,将检查该变量。如果它是假的,那么当循环第一次开始时它将是,添加了开始<product>标记。然后将该变量设置为true。下次循环开始时,不会打印开始标记。

第二个更改是关闭</product>标记已从循环中删除并放在外面。

这些更改的结果是,只有一个包含产品详细信息的开放<product>标记,而可能有多个<category>标记,具体取决于从数据库返回的数据。

此外,除了@Marc B关于(ab)使用PHP 5.3闭包的优秀提示之外,您还应该了解一件事:您的代码包含SQL Injection vulnerability。您正在直接从用户那里获取输入并将其传递给SQL而不会正确地转义它。因为你正在使用笨重和破旧的“mysql”扩展,所以你只有一个可行的选项:mysql_real_escape_string。你可以这样使用它:

$productQuery = mysql_query(
    "select ... where ... and a.productID = " 
    . mysql_real_escape_string($productID)
);

非常重要您正确地逃避了所有用户提供的数据库输入。其他更现代的数据库适配器可以为您提供简单,先进的自动保护。请考虑长期转换为PDOmysqli


回答您对类别的跟进。

首先,您需要在查询中添加ORDER BY子句,并设置为categoryID列的排序。

接下来,您需要修改循环。初始化一个新变量以保存最后一行的categoryID。在循环外部将其设置为null。

在循环内部,在do-we-need-a - <product> - 标记检查之后,检查当前 categoryID。如果它与最后一个categoryID不同,我们需要做两件事:

  1. 如果最后一个categoryID不是null,则表示我们现在已完成处理上一个类别,并应发出</category>结束标记。
  2. 如果最后一个categoryID与当前categoryID不同,那么我们需要打开一个新的<category>标记并提供我们的详细信息。
  3. 在这两个检查之后将出现预期的子类别XML。打印子类别后,*将 last categoryID设置为当前 categoryID。

    您还需要修改上一个结束标记,添加</category>

    请注意,这组逻辑要求结果集中的所有categoryID都不为null。如果获得null类别,则需要相应地更新close-and-reopen逻辑。

    (您可能希望花时间给自己一个关于循环和条件逻辑的复习;您很可能在该领域存在知识差距。通常这些主题在教程和教育材料之前< / em> SQL和XML之类的东西。)