I have 2 xmls (they happen to be android text resources), the first one is:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="TXT_T1">AAAA</string>
</resources>
and the second is
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="TXT_T2">BBBB</string>
</resources>
I know the attribute of the element that I want to copy, in my example it's TXT_T1. Using python, how to copy it to the other xml and paste it right behind TXT_T2?
lxml is the king of xml parsing. I'm not sure if this is what you are looking for, but you could try something like this
from lxml import etree as et
# select a parser and make it remove whitespace
# to discard xml file formatting
parser = et.XMLParser(remove_blank_text=True)
# get the element tree of both of the files
src_tree = et.parse('src.xml', parser)
dest_tree = et.parse('dest.xml', parser)
# get the root element "resources" as
# we want to add it a new element
dest_root = dest_tree.getroot()
# from anywhere in the source document find the "string" tag
# that has a "name" attribute with the value of "TXT_T1"
src_tag = src_tree.find('//string[#name="TXT_T1"]')
# append the tag
dest_root.append(src_tag)
# overwrite the xml file
et.ElementTree(dest_root).write('dest.xml', pretty_print=True, encoding='utf-8', xml_declaration=True)
This assumes, that the first file is called src.xml and the second dest.xml. This also assumes that the element under which you need to copy the new element is the parent element. If not, you can use the find method to find the parent you need or if you don't know the parent, search for the tag with 'TXT_T2' and use tag.getparent() to get the parent.
This will work only for your simple example:
>>> from xml.dom.minidom import parseString, Document
>>> def merge_xml(dom1, dom2):
node_to_add = None
dom3 = Document()
for node_res in dom1.getElementsByTagName('resources'):
for node_str in node_res.getElementsByTagName('string'):
if 'TXT_T1' == node_str.attributes.values()[0].value:
node_to_add = node_str
break
for node_res in dom2.getElementsByTagName('resources'):
node_str3 = dom3.appendChild(node_res)
for node_str in node_res.getElementsByTagName('string'):
node_str3.appendChild(node_str)
if 'TXT_T2' in node_str.attributes.values()[0].value and node_to_add is not None:
node_str3.appendChild(node_to_add)
return dom3.toxml()
>>> dom2 = parseString('''<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="TXT_T2">BBBB</string>
</resources>''')
>>> dom1 = parseString('''<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="TXT_T1">AAAA</string>
</resources>''')
>>> print merge_xml(dom1, dom2)
<?xml version="1.0" ?><resources>
<string name="TXT_T2">BBBB</string><string name="TXT_T1">AAAA</string></resources>
Related
So I want to make my app name as App5 so I did the following. I went to andriod/app/src/AndriodManifest.xml and edited this file to
android:label="#string/app_name"
And then went to andriod/app/src/res/values/strings.xml and Added my app name as following
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">App<sub><small>5</small></sub></string>
</resources>
But still the subscript isn't working so what did I do wrong
Here your app_name's string is considered to be containing text 'App' and child object sub, that's why it isn't working and you are getting only App instead of App5.
Try instead escaping this <sub><small>5</small></sub> by encapsulating it inside <![CDATA[<sub><small>5</small></sub>]]> so you will have :
<string name="app_name">App<![CDATA[<sub><small>5</small></sub>]]></string>
OR
using html entities and
<string name="app_name">App<sub><small>5</small></sub></string>
(PS : check if your widget accepts and formats html)
UPDATE
I forgot to add < at the beginning and > at the end of ![CDATA[]]
, It has been corrected above
In your activity onCreate method do like this ( using the app_name above)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
//ADD THIS LINE
setTitle(Html.fromHtml( getResources().getString(R.string.app_name)));
...
}
I am trying to read and check all text from Android string.xml file.
the file contains below content:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="status">Finishing <xliff:g id="number">%d</xliff:g> percent.</string>
</resources>
I tried:
import xml.etree.ElementTree as ET
tree = ET.parse(filepath)
root = tree.getroot()
print len(root[0])
# it prints 1
print root[0].text
# it prints Finishing
print root[0][0].text
#it prints %d
How to find a way to print the 3rd text, "percent.", while <xliff:g> tag is gettng in my way.
Any proper way to do it? thanks
In ElementTree, your target text "percent." is modeled as tail of the element xliff:g :
>>> ns = {"xliff": "urn:oasis:names:tc:xliff:document:1.2"}
>>> g = root.find("string/xliff:g", namespaces=ns)
>>> print g.tail
percent.
Or using something closer to your attempted code :
>>> print root[0][0].tail
percent.
I'm working with android studio to develop Android app. I'm working on the creation of a template to use in my applications. I have read the Android IDE Template Format specification and so i start my personal template starting from Dummy template.
I have a .ftl file with the following line of code:
<applicationGestureListenerClazz>${projectPackageName}.listeners.${projectShortName}GestureListener</applicationGestureListenerClazz>
When i execute the template i obtain the following line:
<applicationGestureListenerClazz>org.abubu.dummy.listeners.DummyGestureListener
</applicationGestureListenerClazz>
The variables are correctly defined (in other file they work fine). I don't known why.. it add a CRLF after this line.
Anybody has analogue problem?
UPDATE
I discover that the problem is linked to extension of output file. For example. I have a file **license_key_strings.txt.ftl* that contains:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- public key di ${projectPackageName}.key-->
<string name="publicKey">${licenseKey}</string>
</resources>
<!-- fine -->
If i use it to create a xml file
<instantiate from="root/key/src/main/res/values/license_key_strings.txt.ftl" to="${keyBaseDir}/src/main/res/values/license_key_strings.xml"/>
I obtain this file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- public key di org.dummy.key-->
<string name="publicKey">
MIIBIjANBgkqhkiG9w0BAQ
</string>
</resources>
But the output filename ends with .txt
<instantiate from="root/key/src/main/res/values/license_key_strings.txt.ftl" to="${keyBaseDir}/src/main/res/values/license_key_strings.txt"/>
The final output become:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- public key di org.dummy.key-->
<string name="publicKey">MIIBIjANBgkqhkiG9w0BAQ</string>
</resources>
<!-- fine -->
I'm working with Android Studio 1.4
I'm looking for a way to document a layout file to improve its reusability.
What I'd like is something that produces javadoc in generated R file like this.
I know it is possible to do so when using <declare-styleable>. This :
<declare-styleable name="myStyleable">
<!-- Some comment -->
<attr name="someAttr" format"color" />
</declare-styleable>
Produces this output i'd like to obtain for layout files without success :
public final class R {
/** Some comment */
public static final int someAttr...
}
Does someone know of the mean to achieve this ? I'm interrested in :
Documenting the layout file, so that documentation be available when using R.layout.my_layout
Documenting a particular element of the file, so that the documentation be available when finding it by id f.e. aView.findViewById(R.id.the_id_that_is_documented)
By the way, I found part of the response : for ids it is possible to add comments if the id is defined in a resource file (in res/values) :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- This is a comment -->
<item name="myId" type="id"></item>
</resources>
Will produce this result in R.class :
public final class R {
public static final class id {
/** This is a comment
*/
public static int myId=0x7f050007;
}
This won't work directly in the layout file if you use #+id/some_cute_id
Edit : and here's the answer for layout files. In fact it might work for everything (Found it browsing sdk sources in res/values/public.xml). This :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--
* This layout contains a list that enables to choose a bluetooth device to pair with among paired ones -->
<public type="layout" name="devices_choose" id="0x7f030005" />
</resources>
Produces this output in R :
public final class R {
public static class layout {
/**
* This layout contains a list that enables to choose a bluetooth device to pair with among paired ones
*/
public static final int devices_choose=0x7f030005;
}
}
I must make a few translations for my app.
But when I compile my app, console write:
[2012-11-24 15:31:43 - com.ddm.ctimer.MainForm] W/ResourceType( 4892): Bad XML block: header size 297 or total size 0 is larger than data size 0
[2012-11-24 15:31:43 - com.ddm.ctimer.MainForm] C:\Users\Roman\Desktop\NewTimer\NewTimer\res\values-fr\strings.xml:6: error: Found text "
[2012-11-24 15:31:43 - com.ddm.ctimer.MainForm] В В В В " where item tag is expected
Code:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">CTimer</string>
<!--RUS strings-->
<!--MainForm-->
<string name="main_form_sec">Chronomètre</string>
<string name="main_form_tim"> Minuterie </string>
<string name="main_form_set"> Paramètres </string>
<string name="main_form_bg">#000000</string>
<!--Menu-->
<string name="menu_about">À propos du programme</string>
<string name="menu_buy">Supprimer les annonces</string>
<!--Preferences(Settings)-->
Most probably you have a problem with the encoding, resource files are supposed to be encoded in UTF-8.
Please, try to replace "Chronomètre" with something in plain English and see if your error disappears or moves to the next "translated" line.
It's better to use colors.xml for colors:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="main_form_bg">#000000</color>
</resources>