First of all, thank you for the seniors who tried to help me.
I've a large XML file (below is an example with 2 parents).
Each parent(U7418、U2501) might have subchild、subsubchild...etc like parent U2501 below.
<CircuitRoot Title="projectname" Creator="Lee" Date="2020-08-27">
<Profile Platform="SeriesName" />
<U7418 PartNumber="084.21321" Footprint="PPAK-8P" Value="AONR21321" Description="FET MOS AONR21321 PC DFN 3X3 EP 8P">
<U7418 PartNumber="084.21321" Footprint="PPAK-8P" Ball="4" Pin="G" Page="74" Net="LPS_SW">
<R7403 PartNumber="ZZ.R0402" Info="0R-PAD" Net="GND">
<Q7408 PartNumber="084.03413" Pin="D" />
</R7403>
<R7402 PartNumber="64.20035" Net="LPS_SW_A">
<Q7406 PartNumber="075.00138" Pin="D2" />
</R7402>
<C7401 PartNumber="78.15224" Power="+SDC_IN" />
</U7418>
<U7418 PartNumber="084.21321" Footprint="PPAK" Ball="3" Pin="S#3" Page="74" Power="+SDC_IN" />
</U7418>
<U2501 PartNumber="072.25Q64" Footprint="SOIC8" Value="W25Q64JVSSIQ" Description="IC FLASH">
<U2501 PartNumber="072.25Q64" Footprint="SOIC8" Ball="1" Pin="CS#" Page="25" Net="SPI_CS_ROM_N0">
<R2501 PartNumber="63.47234" Power="3D3V_SPI" />
<R2403 PartNumber="ZZ.R0402" Net="SHD_CS0#">
<U2401 PartNumber="071.01515" Pin="GPIO055/PWM2/SHD_CS0#/BSS_STRAP" />
<R2405 PartNumber="63.R0034" Remark="DY#SKU1" Net="PCH_RSMRST#">
<R2404 PartNumber="ZZ.R0402" Net="PCH_RSMRST#_R">
<U2401 PartNumber="071.01515" Pin="GPIO114/PS2_CLK0A/EC_SCI#" />
</R2404>
<TP2401 PartNumber="ZZ.PAD14" Pin="1" />
<R1709 PartNumber="63.10234" Net="PM_RSMRST#">
<Q1701 PartNumber="75.27002" Pin="3" />
<CPU1 PartNumber="ZZ.00CPU" Pin="RSMRST#" />
<R6414 PartNumber="64.33035L" Net="M_BIST">
<Q6408 PartNumber="84.T3904" Pin="B" />
<U2401 PartNumber="071.01515" Pin="GPIO246/CMP_VREF0" />
<D6403 PartNumber="83.R2003" Net="GND">
<PG4408 PartNumber="ZZ.CLOSE" Net="PWR_CHG_ACOK">
<PU4401 PartNumber="074.09538" Pin="ACOK" />
<PR4426 PartNumber="64.19635" Power="GND" />
</PG4408>
<U2401 PartNumber="071.01515" Pin="VCI_OVRD_IN/GPIO172" />
</D6403>
<C6405 PartNumber="78.10523" Power="GND" />
</R6414>
</R1709>
</R2405>
</R2403>
<R1832 PartNumber="ZZ.R0402" Net="SPI">
<CPU1 PartNumber="ZZ.00CPU" Pin="SPI0_CS0#" />
</R1832>
</U2501>
<U2501 PartNumber="072.25Q64" Footprint="SOIC8" Power="3D3V_SPI" />
</U2501>
</CircuitRoot>
My goal is check whether has some specify child.tag(ex:R7403、PR4426) under parents(ex: U7418、U2501) ,also check whether Power or Net in specify child.attrib is GND.
So, I want to extract each parent's(U7418、U2501) child.tag and child.attirb
expect output is
{
U7418:{ R7402:[{PartNumber="64.20035" Net="LPS_SW_A"}], Q7406:[{PartNumber="075.00138" Pin="D2"}]... },
U2501:{ R2403:[{PartNumber="ZZ.R0402" Net="SHD_CS0#"}], PR4426:[{PartNumber="64.19635" Power="GND"}]...},
...
}
but i think this expect output can be changed, since here might have better way to achieve my goal, the key point for me is how to paring this file.
I have tryed
import xml.etree.ElementTree as ET
tree = ET.parse(xml)
parent_map = {}
for p in tree.iter():
for c in p:
if c in parent_map:
parent_map[c.tag].append(c.attrib)
else:
parent_map[c.tag] = [c.attrib]
print(parent_map)
can get all child、subshild...tag and attrib, but i can't get the corresponding parent.
[1]: https://i.stack.imgur.com/hpAmA.png
Thank you for your patience in reading to the end,
All help is greatly appreciated!
Related
Using python3 I am trying to read an xml file and recalculate values based on the attributes within the Item, then write a copy of entire xml file with new values.
Example of xml file (about 10k rows in full file):
<?xml version="1.0" encoding="utf-8"?>
<Items>
<Item id="headscarf_d"
name="{=wW3iouiU}Hijab"
mesh="headscarf_d"
culture="Culture.aserai"
weight="0.5"
value="63"
appearance="1"
Type="HeadArmor">
<ItemComponent>
<Armor head_armor="3"
has_gender_variations="false"
beard_cover_type="type3"
hair_cover_type="all"
modifier_group="cloth_unarmoured"
material_type="Cloth"/>
</ItemComponent>
<Flags Civilian="true"
UseTeamColor="true" />
</Item>
<Item id="open_head_scarf"
name="{=qsVRoGUv}Open Head Scarf"
mesh="aserai_helmet_c"
culture="Culture.aserai"
weight="0.6"
value="174"
appearance="1"
Type="HeadArmor">
<ItemComponent>
<Armor head_armor="5"
has_gender_variations="false"
beard_cover_type="type3"
hair_cover_type="all"
modifier_group="cloth_unarmoured"
material_type="Cloth"/>
</ItemComponent>
<Flags Civilian="true"
UseTeamColor="true" />
</Item>
<Item id="woven_turban"
name="{=ArPvuBYK}Woven Turban"
subtype="head_armor"
mesh="aserai_helmet_h"
culture="Culture.aserai"
weight="0.8"
difficulty="0"
value="250"
appearance="1"
Type="HeadArmor">
<ItemComponent>
<Armor head_armor="6"
has_gender_variations="false"
beard_cover_type="type2"
hair_cover_type="all"
modifier_group="cloth_unarmoured"
material_type="Cloth"/>
</ItemComponent>
<Flags Civilian="true"
UseTeamColor="true" />
</Item>
</Items>
Taking a single item from the example xml,
<Item id="headscarf_d"
name="{=wW3iouiU}Hijab"
mesh="headscarf_d"
culture="Culture.aserai"
weight="0.5"
value="63"
appearance="1"
Type="HeadArmor">
<ItemComponent>
<Armor head_armor="3"
has_gender_variations="false"
beard_cover_type="type3"
hair_cover_type="all"
modifier_group="cloth_unarmoured"
material_type="Cloth"/>
</ItemComponent>
<Flags Civilian="true"
UseTeamColor="true" />
For simplicity say I wanted to take the Item value (63 above example) and divide by 2 (63/2=31.5). Then if the Item's ItemComponent material_type="Cloth" divide by 2 again (31.5/2=15.75). Finally round to an integer before updating the value and repeating for each item then writing the new updated xml file.
I attempted to use Reading, modifying and writing xml but could not get anything useful.
You are probably looking for something along these lines:
from lxml import etree
import math
inv="""[your xml above]"""
doc = etree.XML(inv)
values = doc.xpath('//Item')
materials = doc.xpath('Item//ItemComponent//Armor')
for t, m in zip(values,materials):
if m.attrib['material_type'] == 'Cloth':
val = float(t.attrib['value'])/4
t.attrib['value'] = str(math.ceil(val))
else:
t.attrib['value']= str(math.ceil(val*2))
print(etree.tostring(doc).decode())
The output is your xml with the Items/Item/#value attribute value divided by 2 or 4, as necessary, and rounded up by math.ceil(). Since all Items in your example have cloth as the value of the attribute material_type, they were all divided by 4 and rounded up to:
16
44
63
I am having the below XML:
<orders>
<order xmlns:amz="http://www.amazon.co">
<amz:comp>amz</amz:comp>
</order>
<order xmlns:ebay="http://www.ebay.co">
<ebay:comp>ebay</ebay:comp>
</order>
</orders>
I checked the xpath expressions like //orders/order it is working but in groovy it is not working I'm not getting what is wrong.
Below is the code that I am using:
import groovy.xml.*;
def source = '''<orders>
<order xmlns:amz="http://www.amazon.co">
<amz:comp>amz</amz:comp>
</order>
<order xmlns:ebay="http://www.ebay.co">
<ebay:comp>ebay</ebay:comp>
</order>
</orders>'''
def root = new XmlSlurper().parseText(source).declareNamespace([
amz: "http://www.amazon.co",
ebay: "http://www.ebay.co"
])
println root.orders
println root.orders.order."amz:comp"
I am not getting any output for the above code.
In your example, root variable refers to the <orders> element, so when you call root.orders it is like you were looking for
<orders>
<orders>...</orders>
</orders>
Rename root variable to orders and do
println orders
println orders.order."amz:comp"
to get the following output:
amzebay
amz
Currently I am working with JDBC Spring Integration (to be very specific: <int-jdbc:stored-proc-outbound-gateway>) where the scenario is passing n-number of parameters to a stored procedure (ORACLE) and receive one return variable (with '1' or Error Message) along with n-number of CURSORS (sys_refcursor) which may have n-number of columns.
While working on this above scenario with Spring Framework I noticed the following issue(s):
My logic from front-end was, first read the 'return variable'. If that value is 1 then start reading all the CURSORS data or else through exception by redirecting user to the error page. Now, all my CURSORS were not having same number of columns as well as same length/type of data. And in middle layer I was having only one Model class to deal with all the CURSORS return elements. That was the challenge for me!
Previously I dealt with only one CURSOR. and therefore in middle layer I used Mapper class to map all CURSOR elements to my Model element's (getter and setter) to push data to the front. But then when used same concept to deal with n-number of CURSORS -that was truly a nightmare.
let me share what I did before and what I did later to resolve this situation at my end and then will draw my understanding for which will sick EXPARTS opinion at the later part of this post.
For one return variable (with '1' or Error Message) along with one CURSOR:
I had my Gateway definition as follows:
<!-- Stored Procedure Outbound-Gateway = To call a database stored procedure -->
<int-jdbc:stored-proc-outbound-gateway id="outbound-gateway-storedproc-personalinfo"
request-channel="procedureRequestChannel"
data-source="dataSource"
stored-procedure-name="pkg_personalinfo_spring.proc_personalinfo_spring"
expect-single-result="false"
ignore-column-meta-data="true">
<!-- Parameter Definitions -->
<int-jdbc:sql-parameter-definition name="firstname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="lastname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="p_RetVal" direction="OUT"/>
<int-jdbc:sql-parameter-definition name="get_ResultSet" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
<!-- Parameter Mappings Before Passing & Receiving -->
<int-jdbc:parameter name="firstname" expression="payload[0]"/>
<int-jdbc:parameter name="lastname" expression="payload[1]"/>
<int-jdbc:returning-resultset name="get_ResultSet" row-mapper="com.support.PersonalinfoMapper"/>
</int-jdbc:stored-proc-outbound-gateway>
And in Mapper class I had the following simple Mapping rule:
...
PersonalInfo personalInfo = new PersonalInfo();
try{
personalInfo.setFirstname(resultSet.getString(DBConstants.FIRSTNAME));
personalInfo.setLastname(resultSet.getString(DBConstants.LASTNAME));
...
I did that because in my Model class i was having getter and setter for all CURSOR return elements.
Now, for one return variable (with '1' or Error Message) along with n-number of CURSORS:
I changed my Gateway definition as follows:
<!-- Stored Procedure Outbound-Gateway = To call a database stored procedure -->
<int-jdbc:stored-proc-outbound-gateway id="outbound-gateway-storedproc-personalinfo"
request-channel="procedureRequestChannel"
data-source="dataSource"
stored-procedure-name="pkg_personalinfo_spring.proc_personalinfo_spring"
expect-single-result="false"
ignore-column-meta-data="true">
<!-- Parameter Definitions -->
<int-jdbc:sql-parameter-definition name="firstname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="lastname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="p_RetVal" direction="OUT"/>
<int-jdbc:sql-parameter-definition name="get_curr_1" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
<int-jdbc:sql-parameter-definition name="get_curr_2" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
<!-- Parameter Mappings Before Passing & Receiving -->
<int-jdbc:parameter name="firstname" expression="payload[0]"/>
<int-jdbc:parameter name="lastname" expression="payload[1]"/>
</int-jdbc:stored-proc-outbound-gateway>
And secondly I removed the entire row mapping concept, means I didn't have any Mapper class. The only one thing I had was only one Model class with all the CURSORS element name and their getters and setters.
Also notice that in my 'Parameter Definitions', how added those two CURSORS definition but in 'Parameter Mappings Before Passing & Receiving' I have nothing now.
I ran the App without any exceptions and later through Fiddler observed the following JSON data came with RESPOND, means everything PERFECT! ;)
JSON
- {}
- get_curr_1
- -{}
- - firstname=Faisal
- - lastname=Quazi
- get_curr_2
- -{}
- - country=Bangladesh
- - capital=Dhaka
WHAT THE HACK??? Yes...I had the same feelings ;)
Now, can any one plz help to understand what is going on here. Will it be a true statement that "'int-jdbc:stored-proc-outbound-gateway' is able to MAP ur Model element(s) by itself magically???"
Is there any best practice to deal with such kind of situation(s)?
Thank u guys always :)
:-). I guess that by default Spring JDBC uses ColumnMapRowMapper.
So you end up after that gateway with Map<String, <Map<?, ?>>> or something similar. But it is Map anyway.
Since you further convert your payload to JSON and Jackson can get deal with maps prefectly, you finish with correct result.
I can debug it, of course, but deduction says that it can't be differently.
UPDATE
As I said. The answer is here JdbcTemplate#extractOutputParameters:
....
if (outParam.isResultSetSupported()) {
returnedResults.putAll(processResultSet((ResultSet) out, outParam));
}
else {
String rsName = outParam.getName();
SqlReturnResultSet rsParam = new SqlReturnResultSet(rsName, new ColumnMapRowMapper());
returnedResults.putAll(processResultSet((ResultSet) out, rsParam));
if (logger.isDebugEnabled()) {
logger.debug("Added default SqlReturnResultSet parameter named '" + rsName + "'");
}
}
....
I have a Field with Name TargetedPeople in a Sharepoint list. This is a Person or User group which can have multiple values.
The CAML I used for Querying is
siteDataQuery.Query = #"<Where><Includes><FieldRef Name='TargetedPeople' LookupId='TRUE'/><Value Type='Integer'>" + webInContext.CurrentUser.ID + "</Value></Includes></Where>";
This works fine if we have set the Allow Multiple Selections for "No" in the field. But this seems like not working for if it set to "Yes".
Please share me how to query a multiple field.
After some changes I was able to figure out this. If the field has multiple values we should define the value Type as LookupMulti. Following is the working code sample
siteDataQuery.Query = #"<Where><Contains><FieldRef Name='TargetedPeople' LookupId='TRUE'/><Value Type='LookupMulti'>" + webInContext.CurrentUser.ID + "</Value></Contains></Where>";
Also works and looks like simpler (tested on SP Online):
<Contains>
<FieldRef Name='TargetedPeople' />
<Value Type="Integer">
<UserID Type="Integer" />
</Value>
</Contains>
I am using with a row mapper expecting it wuold return me the list of my objects but instead it is returning me LinkedHasMap. I want resultset to be List of my mapped objects.
Any idea how can i achieve this ?
Config
<int-jdbc:stored-proc-inbound-channel-adapter
channel="eventObj"
stored-procedure-name="p_get_completed_data"
data-source="dataSource"
auto-startup="true"
id="completedEventAdpt"
ignore-column-meta-data="true"
is-function="false"
return-value-required="false">
<int:poller max-messages-per-poll="1" fixed-rate="180000"/>
<int-jdbc:returning-resultset name="mapper" row-mapper="mapper" />
</int-jdbc:stored-proc-inbound-channel-adapter>
<bean id="mapper" class="com.db.mapper.MyMapper"/>
Stored procedures can return multiple result sets, keyed by the parameter name.
In your case, you only have one result set, but it's still returned in a map.
Simply add a <transformer/> after the inbound adapter...
<transformer ... expression="payload['mapper']" />