MySQL 查询的 XML 输出

发布于 2024-09-01 23:50:24 字数 687 浏览 2 评论 0原文

是否有机会将 MySQL 查询的输出直接获取为 XML?

我指的是 MSSQL 具有 SQL-XML 插件的内容,例如:

SELECT * FROM table WHERE 1 FOR XML AUTO

返回文本(或准确地说,是 MSSQL 中的 xml 数据类型),其中包含生成的 XML 标记结构 根据表中的列。

使用 SQL-XML 还可以选择显式定义输出 XML 结构,如下所示:

SELECT
  1       AS tag,
  NULL    AS parent,
  emp_id  AS [employee!1!emp_id],
  cust_id    AS [customer!2!cust_id],
  region    AS [customer!2!region]
 FROM table
 FOR XML EXPLICIT

它会生成如下 XML 代码:

<employee emp_id='129'>
   <customer cust_id='107' region='Eastern'/>
</employee>

您有任何线索如何在MySQL?

预先感谢您的回答。

is there any chance of getting the output from a MySQL query directly to XML?

Im referring to something like MSSQL has with SQL-XML plugin, for example:

SELECT * FROM table WHERE 1 FOR XML AUTO

returns text (or xml data type in MSSQL to be precise) which contains an XML markup structure generated
according to the columns in the table.

With SQL-XML there is also an option of explicitly defining the output XML structure like this:

SELECT
  1       AS tag,
  NULL    AS parent,
  emp_id  AS [employee!1!emp_id],
  cust_id    AS [customer!2!cust_id],
  region    AS [customer!2!region]
 FROM table
 FOR XML EXPLICIT

which generates an XML code as follows:

<employee emp_id='129'>
   <customer cust_id='107' region='Eastern'/>
</employee>

Do you have any clues how to achieve this in MySQL?

Thanks in advance for your answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

帅气尐潴 2024-09-08 23:50:24

mysql命令可以直接输出XML,使用--xml 选项,该选项至少早在 MySql 4.1 就可用。

但是,这不允许您自定义 XML 输出的结构。它将输出类似这样的内容:

<?xml version="1.0"?>
<resultset statement="SELECT * FROM orders" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <row>
    <field name="emp_id">129</field>
    <field name="cust_id">107</field>
    <field name="region">Eastern</field>
  </row>
</resultset>

您想要:

<?xml version="1.0"?>
<orders>
  <employee emp_id="129">
    <customer cust_id="107" region="Eastern"/>
  </employee>
</orders>

可以使用脚本通过 XSLT 完成转换像这样:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="resultset">
    <orders>
      <xsl:apply-templates/>
    </orders>
  </xsl:template>

  <xsl:template match="row">
    <employee emp_id="{field[@name='emp_id']}">
      <customer
        cust_id="{field[@name='cust_id']}"
        region="{field[@name='region']}"/>
    </employee>
  </xsl:template>

</xsl:stylesheet>

这显然比简洁的 MSSQL 语法更冗长,但另一方面它更强大,可以完成 MSSQL 中不可能完成的各种事情。

如果您使用命令行 XSLT 处理器(例如 xsltprocsaxon),则可以将 mysql 的输出直接通过管道传输到 XSLT 程序中。例如:

mysql -e 'select * from table' -X database | xsltproc script.xsl -

The mysql command can output XML directly, using the --xml option, which is available at least as far back as MySql 4.1.

However, this doesn't allow you to customize the structure of the XML output. It will output something like this:

<?xml version="1.0"?>
<resultset statement="SELECT * FROM orders" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <row>
    <field name="emp_id">129</field>
    <field name="cust_id">107</field>
    <field name="region">Eastern</field>
  </row>
</resultset>

And you want:

<?xml version="1.0"?>
<orders>
  <employee emp_id="129">
    <customer cust_id="107" region="Eastern"/>
  </employee>
</orders>

The transformation can be done with XSLT using a script like this:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="resultset">
    <orders>
      <xsl:apply-templates/>
    </orders>
  </xsl:template>

  <xsl:template match="row">
    <employee emp_id="{field[@name='emp_id']}">
      <customer
        cust_id="{field[@name='cust_id']}"
        region="{field[@name='region']}"/>
    </employee>
  </xsl:template>

</xsl:stylesheet>

This is obviously way more verbose than the concise MSSQL syntax, but on the other hand it is a lot more powerful and can do all sorts of things that wouldn't be possible in MSSQL.

If you use a command-line XSLT processor such as xsltproc or saxon, you can pipe the output of mysql directly into the XSLT program. For example:

mysql -e 'select * from table' -X database | xsltproc script.xsl -
メ斷腸人バ 2024-09-08 23:50:24

在 MySQL 中使用 XML 似乎是一个很好的起点从 MySQL 查询到 XML 的不同方法。

来自文章:

   use strict;
   use DBI;
   use XML::Generator::DBI;
   use XML::Handler::YAWriter;

   my $dbh = DBI->connect ("DBI:mysql:test",
                           "testuser", "testpass",
                           { RaiseError => 1, PrintError => 0});
   my $out = XML::Handler::YAWriter->new (AsFile => "-");
   my $gen = XML::Generator::DBI->new (
                                   Handler => $out,
                                   dbh => $dbh
                               );
   $gen->execute ("SELECT name, category FROM animal");
   $dbh->disconnect ();

Using XML with MySQL seems to be a good place to start with various different ways to get from MySQL query to XML.

From the article:

   use strict;
   use DBI;
   use XML::Generator::DBI;
   use XML::Handler::YAWriter;

   my $dbh = DBI->connect ("DBI:mysql:test",
                           "testuser", "testpass",
                           { RaiseError => 1, PrintError => 0});
   my $out = XML::Handler::YAWriter->new (AsFile => "-");
   my $gen = XML::Generator::DBI->new (
                                   Handler => $out,
                                   dbh => $dbh
                               );
   $gen->execute ("SELECT name, category FROM animal");
   $dbh->disconnect ();
溇涏 2024-09-08 23:50:24

你知道如何在 MySQL 中实现这一点吗?

是的,步行并使用 CONCAT 字符串自行制作 xml。尝试

SELECT concat(';') FROM table

我从 2009 年的答案中获取了这个如何转换 MySQL DB 到 XML? 它似乎仍然有效。不是很方便,如果每个项目都有很大的树,它们都将位于根项目的一个串联值中,但它有效,请使用虚拟模型查看此测试:

SELECT concat('<客户 cust_id="', 2, '" 区域="', 3, '"/>') FROM DUAL< /code>

给出

通过“手动编码”,您可以得到这个结构。

<?xml version="1.0"?>
<orders>
  <employee emp_id="1">
    <customer cust_id="2" region="3" />
  </employee>
</orders>

我用每个根项更大的树对此进行了检查,它起作用了,但我必须在其上运行额外的 Python 代码,以消除当 xml 路径中具有中等级别节点时生成的过多开口和闭合。可以将向后查找列表与临时集中的条目一起使用,我已经完成了,但是面向对象的方式会更专业。我只是编写代码,以便在找到新的头项后立即从列表中删除最后 x 项,以及嵌套分支的一些其他技巧。工作了。

我想出了一个找到标签之间每个文本的正则表达式:

string = "     <some tag><another tag>test string<another tag></some tag>"
pattern = r'(?:^\s*)?(?:(?:<[^\/]*?)>)?(.*?)?(?:(?:<\/[^>]*)>)?'
p = re.compile(pattern)
val = r''.join(p.findall(string))
val_escaped = escape(val)
if val_escaped != val:
    string.replace(val, val_escaped)

这个正则表达式可以帮助您访问标签之间的文本。如果允许您使用 CDATA,那么在任何地方使用它都是最简单的。只需将内容“CDATA”(字符数据)添加到 MySQL 中即可:

<Title><![CDATA[', t.title, ']]></Title>

除了非常奇怪的字符(如 (U+001A))之外,您将不再遇到任何问题,您应该在 MySQL 中替换这些字符。然后,您根本不需要关心转义和替换其余特殊字符。在 1 Mio 上为我工作。 lines xml 文件大量使用特殊字符。

然而:您应该使用 Python 的模块 xmlschema 根据所需的 xml 模式文件验证该文件。当您不被允许使用该 CDATA 技巧时,它会提醒您。

如果您需要不带 CDATA 的完全 UTF-8 格式的内容(这通常是一项任务),那么即使在 1 Mio 行文件中,您也可以通过根据 xml 模式文件逐步验证代码输出(= xml 输出)来实现这一目标( xsd 这就是目标)。这是一项有点繁琐的工作,但只要有耐心就可以完成。
可以使用以下方式进行替换:

  • MySQL 使用replace()
  • Python 使用 string.replace()
  • Python 使用 Regex 替换(虽然我最终不需要它,但它看起来像:re.sub (re.escape(val), 'xyz', i))
  • string.encode(encoding = 'UTF-8',Errors = 'strict')

请注意,编码为 utf-8 是最强大的步骤,它甚至可以抛开上述所有其他三种替代方式。还要注意:它使文本成为二进制,然后您需要将其视为二进制 b'...',因此您可以使用 wb 仅以二进制模式将其写入文件。

最后,您可以在普通浏览器(如 Firefox)中打开 XML 输出进行最终检查并观察 XML 的工作情况。或者使用 xml 扩展在 vscode/codium 中检查它。但这些检查是不需要的,在我的例子中,xmlschema 模块已经很好地显示了一切。还要注意的是,vscode/codium 可以很容易地处理 xml 问题,并且当 Firefox 不能时仍然显示树,因此,您将需要一个验证器或浏览器来查看所有 xml 错误。

使用这个 xml-building-with-mysql 可以完成一个相当大的项目,最后有一个三重嵌套的 xml 树,父节点内有许多重复标签,全部由二维 MySQL 输出组成。

PS

除了 MySQL,您可能更适合使用 MSSQL 服务器等内置工具。这个答案只是关于 XML 构建的手艺,但现在有更好的工具。如果将 XML 混淆在一起需要花费太多时间和精力,请导出到文件并在另一个 SQL 中对其进行处理。

Do you have any clue how to achieve this in MySQL?

Yes, go by foot and make the xml yourself with CONCAT strings. Try

SELECT concat('<orders><employee emp_id="', emp_id, '"><customer cust_id="', cust_id, '" region="', region, '"/></employee></orders>') FROM table

I took this from a 2009 answer How to convert a MySQL DB to XML? and it still seems to work. Not very handy, and if you have large trees per item, they will all be in one concatenated value of the root item, but it works, see this test with dummies:

SELECT concat('<orders><employee emp_id="', 1, '"><customer cust_id="', 2, '" region="', 3, '"/></employee></orders>') FROM DUAL

gives

<orders><employee emp_id="1"><customer cust_id="2" region="3"/></employee></orders>

With "manual coding" you can get to this structure.

<?xml version="1.0"?>
<orders>
  <employee emp_id="1">
    <customer cust_id="2" region="3" />
  </employee>
</orders>

I checked this with a larger tree per root item and it worked, but I had to run an additional Python code on it to get rid of the too many openings and closings generated when you have medium level nodes in an xml path. It is possible using backward-looking lists together with entries in a temporary set, and I got it done, but an object oriented way would be more professional. I just coded to drop the last x items from the list as soon as a new head item was found, and some other tricks for nested branches. Worked.

I puzzled out a Regex that found each text between tags:

string = "     <some tag><another tag>test string<another tag></some tag>"
pattern = r'(?:^\s*)?(?:(?:<[^\/]*?)>)?(.*?)?(?:(?:<\/[^>]*)>)?'
p = re.compile(pattern)
val = r''.join(p.findall(string))
val_escaped = escape(val)
if val_escaped != val:
    string.replace(val, val_escaped)

This Regex helps you to access the text between the tags. If you are allowed to use CDATA, it is easiest to use that everywhere. Just make the content "CDATA" (character data) already in MySQL:

<Title><![CDATA[', t.title, ']]></Title>

And you will not have any issues anymore except for very strange characters like (U+001A) which you should replace already in MySQL. You then do not need to care for escaping and replacing the rest of the special characters at all. Worked for me on a 1 Mio. lines xml file with heavy use of special characters.

Yet: you should validate the file against the needed xml schema file using Python's module xmlschema. It will alert you when you are not allowed to use that CDATA trick.

If you need a fully UTF-8 formatted content without CDATA, which might often be the task, you can reach that even in a 1 Mio lines file by validating the code output (= xml output) step by step against the xml schema file (xsd that is the aim). It is a bit fiddly work, but it can be done with some patience.
Replacements are possible with:

  • MySQL using replace()
  • Python using string.replace()
  • Python using Regex replace (though I did not need it in the end, it would look like: re.sub(re.escape(val), 'xyz', i))
  • string.encode(encoding = 'UTF-8', errors = 'strict')

Mind that encoding as utf-8 is the most powerful step, it could even put aside all three other replacement ways above. Mind also: It makes the text binary, you then need to treat it as binary b'...' and you can thus write it to a file only in binary mode using wb.

As the end of it all, you may open the XML output in a normal browser like Firefox for a final check and watch the XML at work. Or check it in vscode/codium with an xml Extension. But these checks are not needed, in my case the xmlschema module has shown everything very well. Mind also that vscode/codium can can handle xml problems quite easily and still show a tree when Firefox cannot, therefore, you will need a validator or a browser to see all xml errors.

Quite a huge project could be done using this xml-building-with-mysql, at the end there was a triple nested xml tree with many repeating tags inside parent nodes, all made from a two-dimensional MySQL output.

PS

Instead of MySQL, you might be better of with built-in tools of MSSQL server and the like. This answer was about the mere handycraft of XML building, but there are better tools nowadays. Export to a file and work on it in another SQL if puzzling the XML together takes too much time and nerves.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文