【问题标题】:insert XML data into mysql with php使用php将XML数据插入mysql
【发布时间】:2013-04-12 16:52:37
【问题描述】:

代表问题的 xml 文件部分(xml 文件有数百个客户记录)

    <?xml version="1.0" encoding="utf-8"?>
    <test>
       <customer>   
          <name>customer 1</name>
          <address>address 1</address>
          <city>city 1</city>
          <state>state 1</state>
          <zip>zip 1</zip>
          <phone>phone 1</phone>
          <buyerinfo>
             <shippingaddress>
               <name>ship to</name>
               <address>Ship address1</address>
             </shippingaddress>
           </buyerinfo>
           <shippingDetail>
             <saletax>
               <saletaxamount>2</saletaxamount>
             </saletax>
           </shippingDetail>
       </customer>...

下面是我的代码

 //Xml string is parsed and creates a DOM Document object
    $responseDoc = new DomDocument();        
    $responseDoc->load('test.xml');     
    foreach ($responseDoc->getElementsByTagName('customer') as $customer){

     $sSQL = sprintf(
    "INSERT INTO customer (name, address, city, state, zip, phone, shipto, shipadderss, tax) 
    VALUES ('%s','%s', '%s', '%s','%s','%s', '%s','%s','%s')",
    mysql_real_escape_string($customer->getElementsByTagName('name')->item(0)->nodeValue),
    mysql_real_escape_string($customer->getElementsByTagName('address')->item(0)->nodeValue),
    mysql_real_escape_string($customer->getElementsByTagName('city')->item(0)->nodeValue),
    mysql_real_escape_string($customer->getElementsByTagName('state')->item(0)->nodeValue),
    mysql_real_escape_string($customer->getElementsByTagName('zip')->item(0)->nodeValue),
    mysql_real_escape_string($customer->getElementsByTagName('phone')->item(0)->nodeValue)
    ?
    ?
    ?       
);
$rResult = mysql_query($sSQL);

if(mysql_errno() > 0)
{
    printf(
        '<h4 style="color: red;">Query Error:</h4>
        <p>(%s) - %s</p>
        <p>Query: %s</p>
        <hr />',
        mysql_errno(),
        mysql_error(),
        $sSQL
    );
}

    }

问题:

  1. 我如何访问获取 customer.buyerinfo.shippingaddress.name 节点值使用 mysql_real_escape_string 在我的插入语句中?用“???”表示

    事实上我有两个节点名称相同的节点"name",一个 是 customer.name 而另一个是 customer.buyerinfo.shippingaddress.name 命名会造成问题 使用 getElementsByTagName "name" 标签来获取值。

  2. 与第一个相同,但如何获取 saletaxamount 节点数据值?

    请帮忙。谢谢!

【问题讨论】:

  • 1.您的代码中没有???。任何你为什么要制作如此邪恶的代码组合?从 XML 中提取您的值 THEN 构建您的查询。像这样将它们混合在一起会导致完全无法阅读的无用混乱。
  • @Marc B. 感谢您的友好反馈。我的意思是说 ”???”在我的插入语句中。向您学习“完全无法阅读的无用混乱”。哇!谢谢你。

标签: php mysql xml mysql-real-escape-string xmldom


【解决方案1】:

对于您拥有的 XML 数据,我更喜欢 SimpleXML 扩展,它包含您需要的一切,而且不需要编写太多代码(它是 DOMDocument 的小妹妹)。

因此,对于输入数据中的每个 customer,您希望获取 9 个左右的值。您可以将这些值表示为 xpath:

$values = <<<XPATH
(
    name
    |address
    |city
    |state
    |zip
    |phone
    |buyerinfo/shippingaddress/name
    |buyerinfo/shippingaddress/address
    |shippingDetail/saletax/saletaxamount
)
XPATH;

这类似于数据库查询。为 Xpath 语言中的 XML 创建一个包含查询的字符串。

我们对 SQL 也做同样的事情,因为两者应该齐头并进,所以这里是相应的 SQL 模式:

$pattern = <<<SQL
INSERT INTO customer
  (
    name, address, city, state, zip, phone, shipto, shipadderss, tax
  )
  VALUES
  (
    '%s','%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'
  )
SQL;

现在只需打开 XML 并指定要处理的客户元素:

$customers = simplexml_load_string($test)->customer; // "test.xml"

然后您只需要遍历每个客户,获取值,转义它们,将它们插入查询并运行 SQL 查询(或创建一个包含多条记录的更大查询):

foreach ($customers as $customer) 
{
    $data = $customer->xpath($values);
    $escaped = array_map('mysql_real_escape_string', $data);
    $query = vsprintf($pattern, $escaped);

    // you can now run the query now
    // ...
}

是的,这已经是您的代码了。如您所见,利用数组、xpath 和 SQL,您可以大大简化此操作。

对于您的示例 XML 中的第一个 客户,这将生成以下查询:

INSERT INTO customer
  (
    name, address, city, state, zip, phone, shipto, shipadderss, tax
  )
  VALUES
  (
    'customer 1','address 1', 'city 1', 'state 1', 'zip 1', 'phone 1', 'ship to', 'Ship address1', '2'
  )

整个代码示例:

$values = <<<XPATH
(
    name
    |address
    |city
    |state
    |zip
    |phone
    |buyerinfo/shippingaddress/name
    |buyerinfo/shippingaddress/address
    |shippingDetail/saletax/saletaxamount
)
XPATH;

$pattern = <<<SQL
INSERT INTO customer
  (
    name, address, city, state, zip, phone, shipto, shipadderss, tax
  )
  VALUES
  (
    '%s','%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'
  )
SQL;

$customers = simplexml_load_string($test)->customer; // "test.xml"

foreach ($customers as $customer)
{
    $data = $customer->xpath($values);
    $escaped = array_map('mysql_real_escape_string', $data);
    $query = vsprintf($pattern, $escaped);

    // you can now run the query now
    $result = mysql_query($query);
    if(mysql_errno())
    {
        printf(
            '<h4 style="color: red;">Query Error:</h4>
            <p>(%s) - %s</p>
            <p>Query:
              <pre>%s</pre>
            </p>
            <hr />',
            mysql_errno(),
            htmlspecialchars(mysql_error()),
            htmlspecialchars($query)
        );
    }
}

【讨论】:

  • @ M8R-1jmw5r 感谢您的反馈。以上只是我正在进行的项目的一个示例部分。看起来 xpath 是展平复杂 xml 树的好主意。我会试一试,看看会发生什么。再次感谢您的时间和指导。
  • 是的,如果您需要遍历不同的深度(以及元素值和属性值之间的差异),我真的更喜欢 Xpath。
  • @M8R-1jmw5r 这看起来不错。我有个问题。对其进行了测试,它运行良好,直到我遇到不存在的节点。如何检查节点是否存在,如果存在,插入值否则设置默认值?示例是税收节点。对于某些客户,它不适用。因此 xml 根本不返回税节点。请帮忙。谢谢。
  • 现在才看到你的评论。对于这个答案,这是每个节点始终存在的前提条件。至少对于这里给出的简化形式。如果将功能包装到对象中,则可以处理更高级别的细节,例如为某些属性提供默认值。请参阅我的其他相关答案:Extracting data from HTML using PHP and xPath,它可以表示允许更多控制的对象中的数据。
  • 对不起 necro 和旧线程,但我现在正在看这个,我想知道变量 $test 的内容是什么?它是你的xml文件的url吗?你没有在代码示例中指定这个?
【解决方案2】:

您可以通过shippingaddress 节点内的循环获取子节点值。

类似,之后 mysql_real_escape_string($customer-&gt;getElementsByTagName('phone')-&gt;item(0)-&gt;nodeValue)

添加:

foreach ($customer->getElementsByTagName('buyerinfo') as $buyerinfo)
{
    foreach ($buyerinfo->getElementsByTagName('shippingaddress') as $shippingaddress)
    {
        mysql_real_escape_string($shippingaddress->getElementsByTagName('name')->item(0)->nodeValue),
        mysql_real_escape_string($shippingaddress->getElementsByTagName('address')->item(0)->nodeValue)
    }
}

当然,您必须使用新值修复查询。

这应该是你的工作,抱歉我没有机会测试它

【讨论】:

  • 感谢您的反馈。您能否详细说明使用新值修复查询?代码示例将不胜感激。再次感谢您花费时间、精力和精力帮助解决此问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-25
  • 2012-04-20
相关资源
最近更新 更多