Updating an attribute in XML with MySQL - mysql

I have a chunk of XML stored as a string in a MySQL database, and need to update one of the attributes using a query.
Given the following string:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<town>
<road name="Main" direction="north"/>
</town>
I would need to change it to update the attribute direction to a different value:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<town>
<road name="Main" direction="east"/>
</town>
Is there an easy way to accomplish this? Thanks in advance!
EDIT: The query would be ran in a SQL script file containing various other upgrade queries, which is called by a piece of code in Java.

Checkout PHP's simple XML
http://www.php.net/manual/en/class.simplexmlelement.php
$xml=new SimpleXMLElement($xml);
print $xml->road->attributes('direction') = 'east';

I ended up overriding the upgrade process for that version. Through Java and JDBC I looped through every row and used JAXB to gain access to the attribute that needed to be changed. I would have preferred to do it with full SQL queries. :(

Related

How to get rid of Liquibase includeAll tag with formatted .sql changesets error: Cannot find the declaration of element 'databaseChangeLog'

I am using a Gradle Spring project with liquibase. To run liquibase I am running the jar created by compiling the project. I am trying to use the liquibase "includeAll" tag in an xml changelog to run all formatted sql changelog scripts inside a directory I've called includeAllScriptsTest (currently contains only one .sql file named test.sql with one changeset).
If I try to use includeAll in my master db-changelog file, at run time liquibase returns the error: file:///.../conf/db/db.changelog-master.xml/ is not a recognized file type.
In an attempt to get around this, I reference from my db-changelog-master.xml another xml called includeAll-changelog.xml. In this file I have the includeAll tag, below are the contents of this file.
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="https://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog conf/xsd/dbchangelog-3.8.xsd">
<includeAll path="***/includeAllScriptsTest/" relativeToChangelogFile="true"/>
</databaseChangeLog>
Inside the folder includeAllScriptsTest is a single file called test.sql, with the contents as below:
--liquibase formatted sql
--changeset author:1 dbms:MySQL splitStatements:true endDelimiter://
DROP PROCEDURE IF EXISTS `TESTINCLUDEALL`;//
CREATE PROCEDURE `TESTINCLUDEALL`()
BEGIN
SELECT * FROM TABLE;
END;//
However, this gives me a different error at run time: cvc-elt.1.a: Cannot find the declaration of element 'databaseChangeLog'. I've found online conflicting information regarding whether it is possible to use includeAll with the version of liquibase used by my project. I'm currently using 3.4.1.
cvc-elt.1.a: Cannot find the declaration of element
'databaseChangeLog'
This error is an XML Parsing error, pointing databaseChangeLog is not declared in the xml schema.
May be you can try using following XSD in your changelog:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
<includeAll path="***/includeAllScriptsTest/" relativeToChangelogFile="true"/>
</databaseChangeLog>
If this still doesn't help, please have a look at few points in answer on this post.

Liquibase use a variable to set changeset author

Is it possible to use some kind of variable or property to set the changeset author in a liquibase formatted sql file.
I have tried to set a property in a chnagelog.xml and using the property for the author as show below.
changelog.xml
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
<property name="author" value="my-author"/>
<include file="sql/test_schema.sql"/>
</databaseChangeLog>
And test_schemal.sql
--liquibase formatted sql
--changeset ${author}:1
CREATE SCHEMA IF NOT EXISTS test_schema;
--rollback DROP SCHEMA IF EXISTS test_schema;
However, the author is not set to the author property, "my-author".
I think this could also be done with terraform templating, but is there a way to do this using only liquibase functionality?
Liquibase allows dynamic substitution of properties in changelog files. We can configure multiple properties inside a file and then use them wherever required. In your case, we can just configure property "authorName" with some value and then use it in changelog file using ${authorName} syntax.
Whatever Jorge has mentioned in his answer is correct. Liquibase assigns or prioritizes value for configured property in below order:
As an attribute passed to your liquibase runner.
As a JVM sytem property
As an environment variable
As a CLI attribute if you are running liquibase through command line
In liquibase.properties file
In the parameters block (property element of the DATABASECHANGELOG table)
You can do it as below example code snippet:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
<changeSet author="${authorName}" id="some-unique-id" dbms="${dbType}" context="some-context">
**My SQL query/ transactional logic goes here**
</changeSet>
</databaseChangeLog>
In liquibase.properties file, I will configure these properties as follows:
authorName=Rakhi
dbType=PostgreSQL
Note: above example is using 2 properties (authorName and dbType). You can use only authorName or even more than that.
If you need help with creating "liquibase.properties" file, visit this link
Cheers!
Using property substitution in your changelog
Liquibase allows you to use different ways to can set property values. Liquibase assigns these values in the order specified below:
As an attribute passed to your Liquibase runner.
As a JVM system property.
As an environment variable.
As a CLI attributes if executed from the command line
As a CLI attributes if executed from the command line
command_line parameter if executed from the command line
In the parameters block (property element) of the DATABASECHANGELOG file itself
Check this liquibase doc

Read XML data and save them to mysql database in symfony 4

I have a simple XML file. I need to read the data and save them to mysql database table (1 or 2 tables). The file is like following :
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0" xmlns:g="http://">
<myfile>
<title><![CDATA[All data]]></title>
<stock>
<name><![CDATA[my name]]></name>
<qty><![CDATA[0]]></qty>
<price><![CDATA[4.99]]></price>
<image><![CDATA[http://fashiondropshippers.com/media/catalog/product/i/m/image_463.jpg]]></image>
</stock>
</myfile>
</rss>
I am trying to do that in Symfony 4 using crawler. my codes in my controller are following
$crawler = new Crawler();
$crawler->addContent(file_get_contents('http://localhost/XML/myxml.xml'));
foreach ($crawler as $domElement) {
var_dump($domElement->nodeValue);
}
return new JsonResponse($domElement->nodeValue);
It displays data with errors. Now I need to save those data in mysql database tables. Could you please tell me how to proceed further ?
Many thanks in advance !
Ok. If you want to save data to DB you have to do the following:
Add Doctrine to your project: https://symfony.com/doc/current/doctrine.html#installing-doctrine
Create an entity: https://symfony.com/doc/current/doctrine.html#creating-an-entity-class
Make migrations: https://symfony.com/doc/current/doctrine.html#migrations-creating-the-database-tables-schema and execute them
Save your data to DB https://symfony.com/doc/current/doctrine.html#persisting-objects-to-the-database

Consistent Id of XML output of SQL executed on Data Access Point

I run an application on Exact Oline for eco taxes, using XML output with XSL transformation to generate the HTML forms.
A query like:
select * from me
generates:
<?xml version="1.0" encoding="utf-16"?>
<InvantiveDAPOutput xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--ecotaksen.be Invantive Data Access Point (Unofficial)-->
<!--License 'L740757780' registered to Control INFO B.V..-->
<ResultSets>
<ResultSet Id="0">
<Fields>
<Field>
<Id>0</Id>
<Name>CurrentDivision</Name>
<DatabaseDataType>int32</DatabaseDataTyp...
In my XSL I then use for instance:
<xsl:value-of select="//InvantiveDAPOutput/ResultSets/ResultSet[#Id='4']/Rows/Row/entity_name_singular" />
But when I insert a query somewhere in the process, the Id all change. 1 remains 1 for instance, but the numbers after the new inserted query increase by 1.
Is there a smarter way to make the XSL independent of the number of queries and their order?
Just add the desired name of the result set to your query as a hint:
select /*+ result_set_name('myname') */ * from me
The XML will become like:
<ResultSet Id="0" Name="myname">
You can find the full syntax for execution hints in the documentation. This holds for Exact Online as well as other platforms such as Teamleader or salesforce.

MySQL/MariaDB namespaces xml returns null with ExtractValue

I have some xml data on a MariaDB database and need to do some parsing.
I ve tried using the following code to extraxt some values but no matter what i may try i keep getting null as output
SELECT xmlResponse FROM myDataBase.xmlLogging where id = '1' INTO #xml;
SELECT ExtractValue(#xml, 'node2');
tried also count(node2) to try identify if there is somtheting wrong in my syntaxaccording to this
https://mariadb.com/kb/en/mariadb/documentation/sql-structure-and-commands/functions-and-operators/string-functions/extractvalue/
my xml structure looks like this, with namespacess
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns:SMnamespace xmlns:ns="http://somenamespace.com/WS/">
<ns:Error_spcCode>0</ns:Error_spcCode><ns:Error_spcMessage/>
<ListofData xmlns="http://www.vendor.com/namespeceIO">
<node1>
<node2>text</node2>
<node3>text</node3>
<node4/>
</node1>
</ListofData>
</ns:SMnamespace>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'
MySQL/MariaDB do not support xml namespaces. They support colons in element names however.
The reason that you do not get the node should be an invalid context in you location path try:
SELECT ExtractValue(#xml, '//node2');
Starting an Xpath expression with // means any node in the document.
I found this reference
http://bugs.mysql.com/bug.php?id=51425
and it seems that this is the case for me as well. The xml that i demonstrated was a simplier version of my actual one that contains quite big strings. So it seems as soon as i reduced the string size, i could get a result.