【问题标题】:Combining XML fields of same name when Loading XML into SQL将 XML 加载到 SQL 时组合同名的 XML 字段
【发布时间】:2018-02-22 16:55:14
【问题描述】:

我正在尝试将 xml 文件加载到 SQL 表中,并且它运行良好,但有一个例外。我有多个同名字段,我想在加载时组合它们。在这种情况下,该领域。目前,它只抓取冗余列名的最后一个实例。

我当前的 XML 具有以下结构:

<item>
    <name>......</name>
    <type>...</type>
    <text>some text</text>
    <text>some more text</text>
    <text>even more text</text>
</item>

这是我的 SQL:

"LOAD XML LOCAL INFILE 'xml/items.xml'
INTO TABLE items
ROWS IDENTIFIED BY '<item>'";

这是我目前在我的 SQL“文本”列中得到的:

even more text

我想要的结果是:

some textsome more textevenmoretext

或者更好的是,如果我可以在实例之间插入一些东西,例如换行符,那将是理想的。

【问题讨论】:

  • 那是你的完整 XML 吗? &lt;item&gt; 是根吗?请发布根目录及其可能包含的任何命名空间。对于 XML 问题总是很重要!

标签: php mysql xml


【解决方案1】:

考虑XSLT,这是一种专门用于转换XML 文件的语言,例如您需要组合&lt;text&gt; 节点。 PHP 可以使用其php-xsl 类运行XSLT 1.0 脚本。

XSLT (另存为.xsl文件,特殊的.xml文件)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- IDENTITY TRANSFORM TO COPY DOCUMENT AS IS -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="item">
    <xsl:copy>
      <xsl:apply-templates select="name|type"/>
      <text>
        <xsl:for-each select="text">
            <xsl:value-of select="."/>
            <xsl:if test="position() != last()">
               <!-- ADD SPACE DELIMITER AFTER EACH ITEM EXCEPT LAST -->
               <!-- REPLACE WITH &#xa; FOR LINE BREAK ENTITY or \n -->
               <xsl:text>&#160;</xsl:text>   
            </xsl:if>
        </xsl:for-each>
      </text>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

PHP

// LOAD XML AND XSLT 
$doc = new DOMDocument();    
$doc->load('Input.xml');

$xsl = new DOMDocument;
$xsl->load('XSLTScript.xsl');

// CONFIGURE TRANSFORMER
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); 

// RUN TRANSFORMATION
$newXML = $proc->transformToXML($doc);

// OUTPUT TO CONSOLE
echo $newXML;

// OUTPUT TO FILE
file_put_contents('Output.xml', $newXML);

输入 XML (假设&lt;items&gt; 为root)

<items>
    <item>
        <name>......</name>
        <type>...</type>
        <text>some text</text>
        <text>some more text</text>
        <text>even more text</text>
    </item>
</items>

输出 XML (在LOAD XML 命令中使用此输出)

<?xml version="1.0" encoding="utf-8"?>
<items>
  <item>
    <name>......</name>
    <type>...</type>
    <text>some text some more text even more text</text>
  </item>
</items>

【讨论】:

  • 这工作完美无缺,谢谢!我的例子是一个相对简化的版本,所以我还有一些工作要做。对于像我这样使用 XAMPP 测试的任何人的说明,您需要进入 php/php.ini 并添加以下“extension=php_xsl.dll”才能使其正常工作。
  • 很高兴一切顺利!不客气。是的,您需要启用 php_xsl 扩展才能使用该类。有时它会默认启用。
【解决方案2】:

将 xml &lt;text&gt; 标签更改为 &lt;text_one&gt;,&lt;text_two&gt;,&lt;text_three&gt;

<item>
    <name>......</name>
    <type>...</type>
    <text_one>some text</text_one>
    <text_two>some more text</text_two>
    <text_three>even more text</text_three>
</item>

然后通过使用CONCAT_WS(),您可以连接文本并将其插入到您的文件中

LOAD XML LOCAL INFILE 'xml/items.xml'  INTO TABLE 
items (@name, @type, @text_one, @text_two, @text_three)   
SET name=@name, type=@type, text= CONCAT_WS(' ',@text_one,@text_two,@text_three);

【讨论】:

  • 问题是我当前的 XML 有数千行。是否有一个 forEach 方法可以将相同元素名称的所有实例连接在一起?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多