GPath expression for finding all attribute values by name - xpath

Looking for GPath expression to get list of attribute values using the attribute name:
def xmltxt = """<reports>
<report category="weather">sunny</report>
<report category="sports">golf</report>
<report category="business">
<subreport category="deals">wallstreet</subreport>
</report>
<report>NA</report>
<report category="life">gossip</report>
</reports>"""
..when searching for all category attributes, I want to get back this, regardless of where category attributes exists in the document:
[weather, sports, business, deals, life]
...but all my attempts retrieve more than what I want, appears it's returning nodes that don't have category attributes; I can remove the empty elements from the list, but I'd like to know why this is happening.
[, weather, sports, business, deals, , life]
def names = xml.'**'.findAll{
it.#category
}.collect{
it.#category
}

def parsed = new XmlParser().parseText( xmltxt )
parsed.'**'*.attribute( 'category' ).findAll()
should do.
Here you go, with XmlSlurper solution:
def parsed = new XmlSlurper().parseText( xmltxt )
parsed.'**'*.attributes().findResults { it.category }

Related

get data from other filed in odoo

I need to get value field2 from list values in field1. Field1 is relation many2many with field in another model.
I tried to use domain for it but everytime I received error.
class filial_page_products(models.Model):
gallery_rstamp_products_ids = fields.Many2many('product.template',
'gallery_rstamp_products_rel',
'gallery_rstamp_products_ids', 'filial_page_new_rstamp_products_ids',
'Gallery products')
default_gallery_product_id = fields.Many2one('product.template','Default maket', domain="[(default_gallery_product_id, 'in', 'filial_page_gallery_rstamp_products_ids')]")
class product(models.Model):
_inherit = 'product.template'
filial_page_gallery_rstamp_products_ids = fields.Many2many('product.template',
'gallery_rstamp_products_rel',
'filial_page_recovery_rstamp_products_ids', 'gallery_rstamp_products_ids',
'Gallery list')
filial_page_default_maket_product_ids = fields.One2many('pr_filials.filial_page_products',
'default_gallery_product_id',
'Linked page products')
How can I use domain to select only those values that are specified in the gallery_rstamp_products_ids field?
of course, I can set default_gallery_product_id from all products but I don't like it.
Your domain doesn't look quite right. The left operand should be quoted and the right side should not be quoted (unless it's actually supposed to be evaluated as a string).
domain="[('default_gallery_product_id', 'in', filial_page_gallery_rstamp_products_ids)]"
Note, there's a special format required for filtering against x2many fields (one2many or many2many). You may need to use this (below), however, there have been reports of issues using this in newer versions.
domain="[('default_gallery_product_id', 'in', filial_page_gallery_rstamp_products_ids[0][2])]"
Here's some documentation on domains.

How to search records with a string which contains some characters of the target field string in Odoo v10?

I am using Odoo v10. While scanning a barcode, a string contains some characters of a char field value. For example,
A field value ('tracknum') = "20171103"
Search the field by entering a string "xxxxxx20171103" or "xxxx20171103yyy"
is there any way to do it?
I have modified the search view :
<field name="tracknum" string="Tracknum" filter_domain="..."/>
How to dig out related records?
You can create an auxiliar computed field like this
custom_name = fields.Char(
string='Custom',
compute='_compute_custom_name',
search='_search_custom_name'
)
#api.multi
#api.depends()
def _compute_custom_name(self):
''' The field has to be a computed field
You do not need to do anything here
'''
pass
def _search_custom_name(self, operator, value):
''' Actually this converts a domain into another one.
With this new domain Odoo can search well
Arguments:
* operator: if you are searchig words it is going to be ilike
* value: the string ro search
The method could return something like this
* [('id', 'in', id_list)]
'''
all_records = self.search([]) # recordset with all the values of the current model
ids = []
if operator == 'ilike':
ids = all_records.filtered(lambda r: r.tracknum in value).mapped('id')
return [('id', 'in', ids)]
Then you can add this field to the search view like this:
<field name="custom_name" string="Tracking Number" />
Keep in mind that it is not a stored field, so it is going to be very inefficient. And you should iterate over all the values each time you want to make a search.
Once you have added the field to the search view it shoul look like this, Tracking Number should appear in the field name

Odoo 10 - Duplicate supplier info for a given product_template

I have:
a) given product_template_id (i.e. id 100) and
b) a duplicated product_template_id (i.e. id 200) created using copy() method
copy() method copies only product.template model, so suppliers for that specific product are not copied.
I would like to duplicate all suppliers for that model, but now I am wondering which is the right way to do it in Odoo.
If I understood the model properly suppliers prices for a given product are stored in product_supplierinfo table, where each record that points to a given product_tmpl_id specifices a supplier price/qty for a given product_template.
Which would be the way in Odoo to search for all records that point to a given product_tmpl_id (i.e. 100), duplicate them changing product_tmpl_id to the new one (i.e. 200)?
Excerpt from the ORM Documentation:
copy (bool) -- whether the field value should be copied when the record is duplicated (default: True for normal fields, False for One2many and computed fields, including property fields and related fields)
The field you're referring to is seller_ids, whose field definition is below:
seller_ids = fields.One2many('product.supplierinfo', 'product_tmpl_id', 'Vendors')
The copy attribute is not explicitly defined, so it is False by default (as explained in the documentation above). If you want this field to copy along with the other values during the standard product "Duplicate" (copy method), you can do this:
class ProductTemplate(models.Model):
_inherit = 'product.template'
# This only changes the copy attribute of the existing seller_ids field.
# All other attributes (string, comodel_name, etc.) remain as they are defined in core.
seller_ids = fields.One2many(copy=True)
Alternatively
If you want to only have the field copied sometimes, you can extend the copy method to look for a specific context value and only copy based on that.
# This may take some tweaking, but here's the general idea
#api.multi
def copy(self, vals):
new_product = super(YourClass, self).copy(vals)
if vals.get('copy_sellers'):
new_product.seller_ids = self.seller_ids.copy({'product_id': new_product.id})
return new_product
# Whatever you have calling the copy method will need to include copy_sellers in vals
vals.update({'copy_sellers': True})
product.copy(vals)

How can i select specific childnodes with LINQ?

I have a node and this node contains 5 childnodes. three of them is RatePlan. How can i select those RatePlan childnodes with LINQ?
Lets clarify something :
my xml is like this :
<hotels>
<hotel id="1" name="hotel 1">
<telephone>123456789</telephone>
<fax>123</fax>
<address>hotels address</address>
<hotelRatePlan>10</hotelRatePlan>
<hotelRatePlan>11</hotelRatePlan>
<hotelRatePlan>12</hotelRatePlan>
</hotel>
<hotel id="2" name="hotel 2">
<telephone>123456789</telephone>
<fax>123</fax>
<address>hotels address</address>
<hotelRatePlan>100</hotelRatePlan>
<hotelRatePlan>110</hotelRatePlan>
<hotelRatePlan>120</hotelRatePlan>
</hotel>
<hotel id="3" name="hotel 3">
<telephone>123456789</telephone>
<fax>123</fax>
<address>hotels address</address>
<hotelRatePlan>10</hotelRatePlan>
<hotelRatePlan>11</hotelRatePlan>
<hotelRatePlan>12</hotelRatePlan>
</hotel>
</hotels>
I am using XMLDocument to read XML file. After i read it i make a selection with SelectNodes. When i get first hotel information i want to select specific childnodes (hotelRatePlan). How can i do that?
Your question isn't particularly clear, but you might just want:
var ratePlans = node.Elements("RatePlan");
That's assuming you're actually using LINQ to XML rather than XmlNode, XmlDocument etc. If you are using the "old" DOM API, you could use:
var ratePlans = node.ChildNodes
.OfType<XmlElement>()
.Where(e => e.LocalName == "RatePlan");
... but I'd moving to LINQ to XML if you can. It's simply a much nicer XML API.
If you are sure that you will only have three rate plans per hotel, then you can load a hotel into an object of type Hotel like so:
XDocument data = XDocument.Load(yourXMLFileNameHere);
//if you have a namespace defined:
XNamespace ns = data.Root.Name.Namespace;
List<Hotels> hotels = (from item in data.Descendants(ns + "hotel")
select new Hotel
{
Id=Convert.ToInt32(item.Attribute("id").Value),
Name=item.Attribute("name").Value,
Telephone=item.Element(ns+"telephone").Value,
Fax=item.Element(ns+"fax").Value,
Address=item.Element(ns+"address").Value,
RatePlan1=item.Element(ns+"hotelRatePlan1").Value,
RatePlan2=item.Element(ns+"hotelRatePlan2").Value,
RatePlan3=item.Element(ns+"hotelRatePlan3").Value
}).ToList<Hotels>();
And then you reference your first rate plan in the following way:
string ratePlan1=hotels[0].RatePlan1;
If the number of your rate plans will vary, you can merge them together into a string like so:
<hotelRatePlans>10 20 30</hotelRatePlans>
Then you change the way you extract your rate plans, and when you need the actual plans, you use the String.Split method to get the array of individual plans.
I think you mean:
var ratePlans = node.ChildNodes.OfType<RatePlan>();

Interacting With Class Objects in Ruby

How can I interact with objects I've created based on their given attributes in Ruby?
To give some context, I'm parsing a text file that might have several hundred entries like the following:
ASIN: B00137RNIQ
-------------------------Status Info-------------------------
Upload created: 2010-04-09 09:33:45
Upload state: Imported
Upload state id: 3
I can parse the above with regular expressions and use the data to create new objects in a "Product" class:
class Product
attr_reader :asin, :creation_date, :upload_state, :upload_state_id
def initialize(asin, creation_date, upload_state, upload_state_id)
#asin = asin
#creation_date = creation_date
#upload_state = upload_state
#upload_state_id = upload_state_id
end
end
After parsing, the raw text from above will be stored in an object that look like this:
[#<Product:0x00000101006ef8 #asin="B00137RNIQ", #creation_date="2010-04-09 09:33:45 ", #upload_state="Imported ", #upload_state_id="3">]
How can I then interact with the newly created class objects? For example, how might I pull all the creation dates for objects with an upload_state_id of 3? I get the feeling I'm going to have to write class methods, but I'm a bit stuck on where to start.
You would need to store the Product objects in a collection. I'll use an array
product_collection = []
# keep adding parse products into the collection as many as they are
product_collection << parsed_product_obj
#next select the subset where upload_state_ud = 3
state_3_products = product_collection.select{|product| product.upload_state_id == 3}
attr reader is a declarative way of defining properties/attributes on your product class. So you can access each value as obj.attribute like I have done for upload_state_id above.
select selects the elements in the target collection, which meet a specific criteria. Each element is assigned to product, and if the criteria evaluates to true is placed in the output collection.

Resources