Extracting XML Data with SQL - sql

I have the following XML data stored in a SQL table
<CustomFields xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.kaseya.com/vsa/2007/12/ServiceDeskDefinition.xsd">
<Field fieldName="ChangeRequest">No</Field>
<Field fieldName="ProblemRecord">No</Field>
<Field fieldName="Source">Email</Field>
<Field fieldName="KB_Article">No</Field>
<Field fieldName="OptimusRef">264692</Field>
<Field fieldName="TimeSpentOnTicket">0.25</Field>
<Field fieldName="PONumber" />
<Field fieldName="ResourceAssignedEngineer" />
What I would like to do is select the TimeSpentOnTicket Value form a stored procedure.
Any ideas how I can do this?

The problem here is your XML. It's invalid, so there's not really a way do search it until you fix it. A simple way to check this is using an online tool like the one at W3Schools. Another issue that I see is that the namespace (xmlns) that you reference no longer exists. I think this will mess up Postgres as well, but I'm not 100% on that. You might to have to filter that out when ingesting. However, after fixing the XML, it's pretty easy to get things out using XPath within the appropriate XML function.
For example, using the following table:
CREATE TABLE BLA.TEMPTABLE (ID INT, MYXML XML)
Then, insert a valid version of your XML:
INSERT INTO BLA.TEMPTABLE ( ID, MYXML )
SELECT 1 as ID,
'<?xml version="1.0" encoding="UTF-8"?>
<CustomFields>
<Field fieldName="ChangeRequest">No</Field>
<Field fieldName="ProblemRecord">No</Field>
<Field fieldName="Source">Email</Field>
<Field fieldName="KB_Article">No</Field>
<Field fieldName="OptimusRef">264692</Field>
<Field fieldName="TimeSpentOnTicket">0.25</Field>
<Field fieldName="PONumber" />
<Field fieldName="ResourceAssignedEngineer" />
</CustomFields>' as MYXML
Then, to query it back out, you can do something like the following (you can test your XPath with a tool like this, if you need to):
SELECT
tt.ID,
tt.MYXML,
XPATH('/CustomFields//Field[#fieldName=''TimeSpentOnTicket'']/text()', tt.MYXML)
FROM
BLA.TEMPTABLE tt

Related

How to reference a planning type in a plan

I have a custom odoo module, which extends some existing modules like hr. I want to create an onboarding plan with several predefined tasks in it.
This is my plan acitivity type xml which works at it should. If I update the applikation with this file, I get the desired tasks in the planning types overview.
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="hr_plan_activity_type_create_work_contract" model="hr.plan.activity.type">
<field name="activity_type_id" ref="mail.mail_activity_data_todo"/>
<field name="responsible">manager</field>
<field name="summary">Create work contract</field>
<field name="note">Create the work contract for the employee.</field>
</record>
<record id="hr_plan_activity_type_employee_model_in_erp" model="hr.plan.activity.type">
<field name="activity_type_id" ref="mail.mail_activity_data_todo"/>
<field name="responsible">manager</field>
<field name="summary">Employee model in ERP</field>
<field name="note">Complete the employee model in ERP (AHV, Banking, etc.)</field>
</record>
</odoo>
This is my plan.xml which should create a plan with the activity types. The creation of the plan works, but if I reference the activity types, I'll get an error message.
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Onboarding -->
<record id="hr_plan_onboarding" model="hr.plan">
<field name="name">Onboarding</field>
<field name="plan_activity_type_ids"
eval="[(6,0,[ref('mycompany.hr_plan_activity_type_employee_model_in_erp')])]"/>
<field name="plan_activity_type_ids"
eval="[(4,0,[ref('mycompany.hr_plan_activity_type_create_work_contract')])]"/>
</record>
</odoo>
In the manifest.py file I first load the plan.activity.type.xml and then the plan.xml so this shouldn't be a problem.
This is the error message I get when I try to upgrade my customized module mycompany:
File "C:\Program Files (x86)\Odoo 13.0e\server\odoo\addons\base\models\ir_model.py", line 1670, in xmlid_lookup
raise ValueError('External ID not found in the system: %s' % xmlid)
odoo.tools.convert.ParseError: "External ID not found in the system: hr.plan.activity.type.hr_plan_activity_type_create_work_contract" while parsing file:/c:/users/myuser/appdata/local/openerp%20s.a/odoo/addons/13.0/mycompany/data/hr/plan.xml:2, near
<odoo>
<!-- Onboarding -->
<record id="hr_plan_onboarding" model="hr.plan">
<field name="name">Onboarding</field>
<field name="plan_activity_type_ids" ref="hr.plan.activity.type.hr_plan_activity_type_create_work_contract"/>
</record>
Does anyone have any ideas?
String identifier stored in ir.model.data, can be used to refer to a record regardless of its database identifier during data imports or export/import roundtrips.
External identifiers are in the form module.id (e.g. account.invoice_graph). From within a module, the module. prefix can be left out.
Sometimes referred to as xml id or xml_id as XML-based Data Files make extensive use of them.
In your example you used model_name.id which probably does not exist in the database, to reference hr_plan_activity_type_create_work_contract record you just need to replace the model name with the module name.
I can see from the log message that the module name is mycompany, try to replace the model name with mycompany:
<record id="hr_plan_onboarding" model="hr.plan">
<field name="name">Onboarding</field>
<field name="plan_activity_type_ids" ref="mycompany.hr_plan_activity_type_create_work_contract"/>
</record>
Update:plan_activity_type_ids is an x2many field
Use the special commands format to set the x2many field values:
<record id="hr_plan_onboarding" model="hr.plan">
<field name="name">Onboarding</field>
<field name="plan_activity_type_ids" eval="[(6,0,[ref('mycompany.hr_plan_activity_type_create_work_contract')])]"/>
</record>
Edit: Only the first one shows up in the GUI
To replaces all existing records in the set by the ids list (using '(6, 0, ids)') you can provide a list of ids inside the triplet. You can find an example in res_partner_demo.xml inside the base module.
Example:
<field name="plan_activity_type_ids" eval="[(6,0,[ref('mycompany.hr_plan_activity_type_employee_model_in_erp'), ref('mycompany.hr_plan_activity_type_create_work_contract')])]"/>
To add an existing record of id id to the set (using (4, id)) you need to provide one id for each triplet. You can find an example in base_groups.xml inside the base module.
Example:
<field name="plan_activity_type_ids" eval="[(4,ref('mycompany.hr_plan_activity_type_employee_model_in_erp')), (4,ref('mycompany.hr_plan_activity_type_create_work_contract'))]"/>
Your ref ids are wrong. hr.plan.activity.type.hr_plan_activity_type_create_work_contract is wrong. You get only one . in a reference. its [<module_name>.]ext_id_of_object.
If you reference the object from the same module you don't have to use module name.part
If you can see the database tables. then things you are referencing are in table ir_model_data
So if the thing you are referencing is in your own model then you cant use just hr_plan_activity_type_create_work_contract as a reference or your_model_name.hr_plan_activity_type_create_work_contract

odoo 9 how to add relational field to pivot view?

I'm customizing Project's pivot view to show timesheet description along with task's name.
here is my code below but when I click pivot view it shows an error
<!-- Insert Project Issue Pivot Field -->
<record id="project_task_custom_pivot" model="ir.ui.view">
<field name="name">project.task.custom.pivot</field>
<field name="model">project.task</field>
<field name="inherit_id" ref="project.view_project_task_pivot"/>
<field name="arch" type="xml">
<field name="stage_id" position="after">
<field name="name" type="row"/>
<field name="timesheet_ids" type="row"/>
</field>
</field>
</record>
Error below
assert groupby_def and groupby_def._classic_write, "Fields in 'groupby' must be regular database-persisted fields (no function or related fields), or function fields with store=True"
Edit
I re-defined the field "timesheet_ids" as #George Daramouskas mentioned.
timesheet_ids = fields.One2many('account.analytic.line', 'task_id', string="Timesheetss", store=True)
But It didn't work.
So I took a look at the source code in Odoo Source
The function "One2many" has no such a parameter.
I guess the Store=True is for only regular field not related field.
Is there any other solution for this?
Thanks
Create your field with the attribute store=True in the constructor so that the field is stored in the database.

sql modify XML node

I'm trying to modify xml attribute in my table:
XML:
<root>
<object name="111">
<fields>
<field name="1">False</ofield>
<field name="VIN">123</field>
</fields>
</object>
</root>
UPDATE wftable
SET XML.modify('replace value of
(root/object[#name="111"]/fields/field/#name[.="VIN"])[1]
with "testNumber"')
WHERE id = 20889436
But I get as a result
<field name="testNumber">123</field>
Actually I just want to update xml node like this:
<field name="VIN">testNumber</field>
How can I modify my UPDATE query?
You need to specify the text() node of field as the node you want to update.
replace value of
(root/object[#name="111"]/fields/field[#name="VIN"]/text())[1]
with "testNumber"

Difference between name and id in an OpenERP form

The code below is a snippet from an OpenERP xml form definition.
<record model="ir.ui.view" id="direct_supplier_invoice_form">
<field name="name">direct_supplier.invoice.form</field>
<field name="model">account.invoice</field>
<field name="type">form</field>
<field name="inherit_id" eval="False" />
<field name="priority">250</field>
<field name="arch" type="xml">
It has two fields that seem very similair:
id="direct_supplier_invoice_form"
<field name="name">direct_supplier.invoice.form</field>
What is the specific purpose of these two fields?
name: is simply the name of the record (field name)
id: is also called xml_id, it's like a name for the records id.
Why is there a name for an id? So you can reference to that id by name instead of numbers (which can vary from installation to installation).
Where are these names saved in db? Just look into table ir_model_data.
I bet you've already used these id-names for references :-)
that's an XML code...
Name refers to the name of the field or record
while ID refers to its reference name so that whenever you are going to access the particular record or field you will have to use its ID.

Avoiding Boxing/Unboxing on unknown input

I am creating an application that parses an XML and retrieves some data. Each xml node specifies the data (const), a recordset's column-name to get the data from (var), a subset of possible data values depending on some condition (enum) and others. It may also specify, alongside the data, the format in which the data must be shown to the user.
The thing is that for each node type I need to process the values differently and perform some actinons so, for each node, I need to store the return value in a temp variable in order to later format it... I know I could format it right there and return it but that would mean to repeat myself and I hate doing so.
So, the question: How can I store the value to return, in a temp variable, while avoiding boxing/unboxing when the type is unknown and I can't use generics?
P.S.: I'm designing the parser, the XML Schema and the view that will fill the recordset so changes to all are plausible.
Update
I cannot post the code nor the XML values but this is the XML structure and actual tags.
<?xml version='1.0' encoding='utf-8'?>
<root>
<entity>
<header>
<field type="const">C1</field>
<field type="const">C2</field>
<field type="count" />
<field type="sum" precision="2">some_recordset_field</field>
<field type="const">C3</field>
<field type="const">C4</field>
<field type="const">C5</field>
</header>
<detail>
<field type="enum" fieldName="some_recordset_field">
<match value="0">M1</match>
<match value="1">M2</match>
</field>
<field type="const">C6</field>
<field type="const">C7</field>
<field type="const">C8</field>
<field type="var" format="0000000000">some_recordset_field</field>
<field type="var" format="MMddyyyy">some_recordset_field</field>
<field type="var" format="0000000000" precision="2">some_recordset_field</field>
<field type="var" format="0000000000">some_recordset_field</field>
<field type="enum" fieldName ="some_recordset_field">
<match value="0">M3</match>
<match value="1">M4</match>
</field>
<field type="const">C9</field>
</detail>
</entity>
</root>
Have you tried using the var type? That way you don't need to know the type of each node. Also, some small sample of your scenario would be useful.