I do have a file that contains lines similar to the following:
<Item Name="INV_LIST" Justification="End" LowestAllowedValue="" DistanceBetweenRecords="0" Width="45" MaximumLength="12" SynchronizedItemName="INVOICE_AMT" PromptDisplayStyle="First Record"/>
<Item Name="INVOICE_AMT_LIST" Justification="End" LowestAllowedValue="" DistanceBetweenRecords="0" Width="48" MaximumLength="22" SynchronizedItemName="" PromptDisplayStyle="First Record"/>
<Item Name="INV_LIST2" Justification="End" LowestAllowedValue="" DistanceBetweenRecords="0" Width="233" MaximumLength="12" SynchronizedItemName="INVOICE_AMT2" PromptDisplayStyle="First Record"/>
I want to run a Linux command like sed or awk, to remove the attribute MaximumLength and its value (it does not matter what it contains between the quotes) whenever there is a line that contains a SynchronizedItemName with a value. If the line contains SynchronizedItemName="", the line will remain untouched.
I want to end with the following:
<Item Name="INV_LIST" Justification="End" LowestAllowedValue="" DistanceBetweenRecords="0" Width="45" SynchronizedItemName="INVOICE_AMT" PromptDisplayStyle="First Record"/>
<Item Name="INVOICE_AMT_LIST" Justification="End" LowestAllowedValue="" DistanceBetweenRecords="0" Width="48" MaximumLength="22" SynchronizedItemName="" PromptDisplayStyle="First Record"/>
<Item Name="INV_LIST2" Justification="End" LowestAllowedValue="" DistanceBetweenRecords="0" Width="233" SynchronizedItemName="INVOICE_AMT2" PromptDisplayStyle="First Record"/>
You can try with this awk script:
{
where = match($0, "SynchronizedItemName=\"\"")
if (where != 0) print
else{
gsub(/MaximumLength=\"[0-9]*\"/, ""); print
}
}
Given your input, I get output as:
<Item Name="INV_LIST" Justification="End" LowestAllowedValue="" DistanceBetweenRecords="0" Width="45" SynchronizedItemName="INVOICE_AMT" PromptDisplayStyle="First Record"/>
<Item Name="INVOICE_AMT_LIST" Justification="End" LowestAllowedValue="" DistanceBetweenRecords="0" Width="48" MaximumLength="22" SynchronizedItemName="" PromptDisplayStyle="First Record"/>
<Item Name="INV_LIST2" Justification="End" LowestAllowedValue="" DistanceBetweenRecords="0" Width="233" SynchronizedItemName="INVOICE_AMT2" PromptDisplayStyle="First Record"/>
If you have xmlstarlet available, you could use the ed command...
NOTE: The "-L" global option modifies the file in-place. Remove this if you do not want to modify the original input file.
xmlstarlet ed -L -d '//Item[normalize-space(#SynchronizedItemName)]/#MaximumLength' input.xml
Using Pankaj code above, put it me the right track.
His code worked with the small set of lines in my example and a few others I added, but on the larger file, it replaced all the elements with MaximumLength.
However, my solution is based on his idea, so thanks Pankaj again.
Here is what I ended up with:
cat tempo | awk '{ ret = match($0, "SynchronizedItemName=\"[0-9A-Za-z_]+\"")
if (ret > 0) {
gsub(/MaximumLength=\"[0-9]*\"/, ""); print $0
}
else {
print $0
}
}' > tmpo_file && mv tmpo_file tempo
The last bit (the redirection), just prints the file to a temporary one and then replaces the original.
Related
I want the length of searchview to occupy full width of action bar when clicked but instead it shows the others items as well. This is xml file of the view
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_settings"
android:title="Settings"
app:showAsAction="never"/>
<item
android:id="#+id/about"
android:title="About"
app:showAsAction="never"
/>
<item
android:id="#+id/edit"
android:icon="#drawable/ic_baseline_sort_24"
app:showAsAction="always"
android:title="Edit"/>
<item android:id="#+id/search"
android:title="search_title"
android:icon="#drawable/ic_search"
app:showAsAction="always|collapseActionView"
app:actionViewClass="androidx.appcompat.widget.SearchView" />
</menu>
In the java file I am trying the following
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView)
item.getActionView();
searchView.setMaxWidth(Integer.MAX_VALUE);
It is working as regular search bar with other items shown as well along the bar.
So I'm creating a custom Ribbon using the Office RibbonX Editor and Excel. I want to display a simple dropdown that allows the user to switch between three worksheets.
I'm not sure why it's going wrong, but I keep running into three errors that correspond to the onAction attribute for each item:
Ln 8, Col 51: The 'onAction' attribute is not declared.
Ln 9, Col 51: The 'onAction' attribute is not declared.
Ln 10, Col 51: The 'onAction' attribute is not declared.
Here is my code:
XML (customUI14.xml file):
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab id="customTab" label="DropDown" insertAfterMso="TabHome">
<group id="customGroup" label="Custom Group">
<dropDown id="dropDown1" label="Dropdown Box">
<item id="dd01" label="Sheet1" imageMso = "_1" onAction="DDOnAction" />
<item id="dd02" label="Sheet2" imageMso = "_2" onAction="DDOnAction" />
<item id="dd03" label="Sheet3" imageMso = "_3" onAction="DDOnAction" />
</dropDown>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
VBA:
Sub DDOnAction(control As IRibbonControl, id As String, index As Integer)
Select Case control.id
Case "dd01"
ActiveWorkbook.Sheets("Sheet1").Activate
Case "dd02"
ActiveWorkbook.Sheets("Sheet2").Activate
Case "dd03"
ActiveWorkbook.Sheets("Sheet3").Activate
End Select
End Sub
Hi the onAction attribute should placed in the dropdown and not in the item,
So the XML is :
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab id="customTab" label="DropDown" insertAfterMso="TabHome">
<group id="customGroup" label="Custom Group">
<dropDown id="dropDown1" label="Dropdown Box" onAction="DDOnAction" >
<item id="dd01" label="Sheet1" imageMso = "_1" />
<item id="dd02" label="Sheet2" imageMso = "_2" />
<item id="dd03" label="Sheet3" imageMso = "_3" />
</dropDown>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
and the code is like this
Sub DDOnAction(control As IRibbonControl, id As String, Index As Integer)
Select Case Index
Case 0
ActiveWorkbook.Sheets("Sheet1").Activate
Case 1
ActiveWorkbook.Sheets("Sheet2").Activate
Case 2
ActiveWorkbook.Sheets("Sheet3").Activate
End Select
End Sub
I've been working with this much of the day but haven't been able to find a solution. I have a fairly large XML file that I need to strip of some data. The 'fields' are annotated using attributes by Id (field name) and Num (unique number for the field name).
<?xml version="1.0" encoding="UTF-8"?>
<Data>
<Item Id="Type" Num="30">3</Item>
<Item Id="Version" Num="50">180</Item>
<Owner>
<Item Id="IdNumber" Num="20">00000000</Item>
<Item Id="race1" Num="160">01</Item>
<Item Id="race2" Num="161">88</Item>
<Item Id="race3" Num="162">88</Item>
<Dog>
<Item Id="Breed" Num="77">Mutt</Item>
<Item Id="Weight" Num="88">88</Item>
</Dog>
<Dog>
<Item Id="Breed" Num="77">Retriever</Item>
<Item Id="Weight" Num="88">77</Item>
</Dog>
</Owner>
<Owner>
<Item Id="IdNumber" Num="20">00033000</Item>
<Item Id="race1" Num="160">03</Item>
<Item Id="race2" Num="161">88</Item>
<Item Id="race3" Num="162">88</Item>
<Dog>
<Item Id="Breed" Num="77">Poodle</Item>
<Item Id="Weight" Num="88">21</Item>
</Dog>
</Owner>
</Data>
Here's the pretty simple python code that I assumed would do the trick, but it's stripping out the data as expected.
#!/usr/bin/env python3
import xml.etree.ElementTree as ET
# list of "Nums" to drop from each Owner and Dog
drops = ['160', '161', '162', '88']
# read in XML file
with open('dogowners.xml') as xmlin:
tree = ET.parse(xmlin)
root = tree.getroot()
for x in root:
for y in x:
# checking to make sure it's an Owner
if y.attrib:
# if the value for attribute Num is in the list of drops then remove it
if y.attrib["Num"] in drops:
x.remove(y)
# finally output new tree
tree.write('output.xml')
output.xml
The issue I'm running into is it's not removing all the drops/Nums listed. In the case with this small XML, it's only doing the first and third value on the Owner level, which is consistent with my large file because it appears to be only removing every other one.
<Data>
<Item Id="Type" Num="30">3</Item>
<Item Id="Version" Num="50">180</Item>
<Owner>
<Item Id="IdNumber" Num="20">00000000</Item>
<Item Id="race2" Num="161">88</Item>
<Dog>
<Item Id="Breed" Num="77">Mutt</Item>
<Item Id="Weight" Num="88">88</Item>
</Dog>
<Dog>
<Item Id="Breed" Num="77">Retriever</Item>
<Item Id="Weight" Num="88">77</Item>
</Dog>
</Owner>
<Owner>
<Item Id="IdNumber" Num="20">00033000</Item>
<Item Id="race2" Num="161">88</Item>
<Dog>
<Item Id="Breed" Num="77">Poodle</Item>
<Item Id="Weight" Num="88">21</Item>
</Dog>
</Owner>
</Data>
I feel like I might be missing something kind of obvious, but XML parsing is not my forte and I've been fighting with this for a couple of hours. Any help is greatly appreciated.
This seems like a good candidate for the identiy transform pattern. The following will copy the xml document, but will exclude the Item elements that match the empty template at the end of the xsl string.
owner-dog.py
#!/usr/bin/env python3
from lxml import etree
# list of "Nums" to drop from each Owner and Dog
drops = ('160', '161', '162', '88')
# we turn it into an xsl attribute pattern:
# #Num = '160' or #Num = '161' or #Num = '162' or #Num = '88'
attr_vals = list(map(lambda n: f'#Num = \'{n}\'', drops))
attr_expr = ' or '.join(attr_vals)
xsl = etree.XML('''<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent='yes'/>
<xsl:strip-space elements="*" />
<!-- copy all nodes ... -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!-- ... except for any elements matching the following template -->
<xsl:template match="//Item[ {attr_vals} ]" />
</xsl:stylesheet>'''.format(attr_vals=attr_expr))
transform = etree.XSLT(xsl)
with open('owner-dog.xml') as xml:
print(transform(etree.parse(xml)))
Output
<?xml version="1.0"?>
<Data>
<Item Id="Type" Num="30">3</Item>
<Item Id="Version" Num="50">180</Item>
<Owner>
<Item Id="IdNumber" Num="20">00000000</Item>
<Dog>
<Item Id="Breed" Num="77">Mutt</Item>
</Dog>
<Dog>
<Item Id="Breed" Num="77">Retriever</Item>
</Dog>
</Owner>
<Owner>
<Item Id="IdNumber" Num="20">00033000</Item>
<Dog>
<Item Id="Breed" Num="77">Poodle</Item>
</Dog>
</Owner>
</Data>
Comparing the original xml with the ouput
diff <(xmllint --format owner-dog.xml) <(./owner-dog.py)
1c1
< <?xml version="1.0" encoding="UTF-8"?>
---
> <?xml version="1.0"?>
7,9d6
< <Item Id="race1" Num="160">01</Item>
< <Item Id="race2" Num="161">88</Item>
< <Item Id="race3" Num="162">88</Item>
12d8
< <Item Id="Weight" Num="88">88</Item>
16d11
< <Item Id="Weight" Num="88">77</Item>
21,23d15
< <Item Id="race1" Num="160">03</Item>
< <Item Id="race2" Num="161">88</Item>
< <Item Id="race3" Num="162">88</Item>
26d17
< <Item Id="Weight" Num="88">21</Item>
29a21
>
I am using Pentaho Data Integration, I created a new transformation and I have 2 steps in it....1 is a CSV file of my data, the second is an Excel file with two columns one is are the state names and the other the sort form of that state name, Example ("New York" "NY")
In my CSV file I have a state columns with the state names "New York" I want to use my excel file to map "New York" with "NY"
I have googled this all day with no clear answer...can anyone help?
You can use Merge Join. Using this you can merge both the files and select the desired columns. Before merging, you have to sort those files according to fields which use are using for mapping. In your case, it will be state name.
I would recommend you to use stream lookup to do this task. Check the test transformation attached. It will do your task.
<?xml version="1.0" encoding="UTF-8"?>
<transformation-steps>
<steps>
<step>
<name>EXCEL</name>
<type>DataGrid</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<fields>
<field>
<name>State</name>
<type>String</type>
<format/>
<currency/>
<decimal/>
<group/>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
<field>
<name>Short_state</name>
<type>String</type>
<format/>
<currency/>
<decimal/>
<group/>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
</fields>
<data>
<line> <item>New York</item><item>TX</item> </line>
<line> <item>Texas</item><item>TX</item> </line>
</data>
<cluster_schema/>
<remotesteps> <input> </input> <output> </output> </remotesteps> <GUI>
<xloc>392</xloc>
<yloc>80</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>CSV</name>
<type>DataGrid</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<fields>
<field>
<name>Full_state_name</name>
<type>String</type>
<format/>
<currency/>
<decimal/>
<group/>
<length>-1</length>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
</field>
</fields>
<data>
<line> <item>New York</item> </line>
<line> <item>Texas</item> </line>
</data>
<cluster_schema/>
<remotesteps> <input> </input> <output> </output> </remotesteps> <GUI>
<xloc>511</xloc>
<yloc>169</yloc>
<draw>Y</draw>
</GUI>
</step>
<step>
<name>Stream lookup</name>
<type>StreamLookup</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
<copies>1</copies>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
<from>EXCEL</from>
<input_sorted>N</input_sorted>
<preserve_memory>Y</preserve_memory>
<sorted_list>N</sorted_list>
<integer_pair>N</integer_pair>
<lookup>
<key>
<name>Full_state_name</name>
<field>State</field>
</key>
<value>
<name>State</name>
<rename>State</rename>
<default/>
<type>String</type>
</value>
<value>
<name>Short_state</name>
<rename>Short_state</rename>
<default/>
<type>String</type>
</value>
</lookup>
<cluster_schema/>
<remotesteps> <input> </input> <output> </output> </remotesteps> <GUI>
<xloc>510</xloc>
<yloc>79</yloc>
<draw>Y</draw>
</GUI>
</step>
</steps>
<order>
<hop> <from>EXCEL</from><to>Stream lookup</to><enabled>Y</enabled> </hop>
<hop> <from>CSV</from><to>Stream lookup</to><enabled>Y</enabled> </hop>
</order>
<notepads>
</notepads>
<step_error_handling>
</step_error_handling>
</transformation-steps>
I am having difficulty adding a node deeper in an xml structure. I am missing something between and node and nodeList. Any help would be greatly appreciated.
def xml='''<Root id="example" version="1" archived="false">
<Item name="one" value="test"/>
<Item name="two" value="test2"/>
<Item name="three" value="test3"/>
<AppSettings Name="foo" Id="foo1">
<roles>foo</roles>
</AppSettings>
<AppSettings Name="bar" Id="bar1">
<Item name="blue" value=""/>
<Item name="green" value=""/>
<Item name="yellow" value=""/>
<Roles>
<Role id="A"/>
<Role id="B"/>
<Role id="C"/>
</Roles>
</AppSettings>
</Root>'''
root = new XmlParser().parseText(xml)
def appSettings = root.'AppSettings'.find{it.#Name == "bar"}.'Roles'
appSettings.appendNode('Role', [id: 'D'])
def writer = new StringWriter()
def printer = new XmlNodePrinter(new PrintWriter(writer))
printer.preserveWhitespace = true
printer.print(root)
String result = writer.toString()
println result
Error
groovy.lang.MissingMethodException: No signature of method: groovy.util.NodeList.appendNode() is applicable for argument types: (java.lang.String, java.util.LinkedHashMap) values: [Role, [id:D]]
This line here:
def appSettings = root.'AppSettings'.find{it.#Name == "bar"}.'Roles'
is returning you a NodeList (containing a single node), so you want to call appendNode on the contents of this list, not on the list itself.
This can be done either by:
appSettings*.appendNode('Role', [id: 'D'])
Which will call appendNode on every element of the list, or by:
appSettings[0]?.appendNode('Role', [id: 'D'])
Which will call appendNode on the first element of the list (if there is a first element thanks to the null-safe operator ?).