Xmlparser.getText() is giving null - java

I'm trying to pull values from a preset xml file and I keep getting null when I try to check what the value was.
if (pulled.equals("preset")) {
presetName = xmlParser.getAttributeValue(null,"name");
Log.d(TAG, presetName + " = " + xmlParser.getText());
}
This is the xml im Pulling the value from
<?xml version="1.0" encoding="utf-8"?>
<sports>
<sport name="Baseball" paid="false">
<preset name="Pitching Mound">726.0</preset>
<preset name="Base Distance">1080.0</preset>
</sport>
<sport name="Basketball" paid="false">
<preset name="NBA Free Throw Line">181.08</preset>
<preset name="NBA 3pt Line">265.8</preset>
</sport>
<sport name="Cricket" paid="true">
<preset name="Cricket Pitch">2012.0</preset>
<preset name="Testing">0.8</preset>
</sport>
</sports>
Am I doing something wrong?

On XmlPullParser api, the getText() method has the following description:
Returns the text content of the current event as String. The value
returned depends on current event type, for example for
TEXT event it is element content (this is typical case when next()
is used). See description of nextToken() for detailed description of
possible returned values for different types of events.
NOTE: in case of ENTITY_REF, this method returns the entity
replacement text (or null if not available). This is the only case
where getText() and getTextCharacters() return different values.
So based on this description, first you have to check if the current xml node is TEXT in order that getText() doesn't return null.
if (pulled.equals("preset")) {
presetName = xmlParser.getAttributeValue(null,"name");
if (xmlParser.getEventType() == XmlPullParser.TEXT) {
Log.d(TAG, presetName + " = " + xmlParser.getText());
}
}
Hope this helps,

Related

SharedPreferences getString returns null

I keep getting null instead of the expected string. I have passed getSharedPreferences the context of the app and the proper key. I'll upload the XML file. I'm not sure what's going on here though.
java.lang.NullPointerException: println needs a message on line
Log.d("MomentPrefTimeStamp", momentData.getString("caption", null));
Nothing in the preference file shows up, however the keys are correct and the momentData is a valid SharedPreferences object. At least according to the debugger.
This is the XML, below is the code.
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="time_stamp">1529509324</string>
<string name="img_uri">content://com.example.android.fileprovider/my_images/JPEG_20180620_114201_1480896410651074556.jpg</string>
<string name="caption">Captionas</string>
</map>
Why am I not able to get my data with the correct key and context?
-
if (prefsDir.exists() && prefsDir.isDirectory()) {
String[] list = prefsDir.list();
Log.d("PrefList", list.toString());
//Iterate through every file in the directory
for (String title : list) {
Log.d("prefTitle", title);
//Only open files with our MOMENT marker, since there will be other shared_pref files inside folder.
String[] momentID = title.split("_");
Log.d("StringMoment", momentID.toString());
Log.d("StringMoment1", momentID[0]);
if (momentID.length > 1) {
Log.d("StringMoment2", momentID[1]);
if (momentID[1].equals("JPEG.xml")) {
Log.d("momentTitle", title);
SharedPreferences momentData = this.getSharedPreferences(title, this.MODE_PRIVATE);
Log.d("MomentPref", momentData.toString());
Log.d("MomentPrefTimeStamp", momentData.getString("caption", null));
moments.add(momentData);
}
}
}
}
return moments;
If you are getting you're SharedPreferences through string tricks and file directories, be sure to trim the extension name off of the file name. I don't know why it was still giving me a SharedPreference Object instead of a null pointer exception, but that is the problem.
1234242_JPEG.xml needs to be 1234242_JPEG to get a proper SharedPreference file.
Below is the fix.
String name = title.substring(0, title.lastIndexOf('.'));
Log.d("MomentName", name);
SharedPreferences momentData = this.getSharedPreferences(name, this.MODE_PRIVATE);

Java regular expression to remove empty xml nodes and childrens completely

I am struggling to find the best solution. Below is my XML :
<Dbtr>
<Nm>John doe</Nm>
<Id>
<OrgId>
<Othr>
<Id/>
</Othr>
</OrgId>
</Id>
</Dbtr>
This is should replaced like this below :
<Dbtr>
<Nm>John doe</Nm>
</Dbtr>
So all the empty nodes and children without any values should be left out.
I am using following expression and it don't work as per my wishes
docStr = docStr.replaceAll("<(\\w+)></\\1>|<\\w+/>", "");
Any help would be really appreciated.
Edit :
I am creating this XML (and not parsing it) this will be sent out to clearing house, who will reject this xml message because of this empty tags. The way I am creating this xml is not in my hand I just provide the values from the db and as you can see some of the values are empty, this code (I have no control) writes out the xml tag already and then writes the value, all I can control is to not write "null".
The best bet for me now is to get the output xml like this and replace it with some regexp logic and form an xml without empty tags, that can pass schema validation.
String xml = ""
+ "<Dbtr>"
+ " <Nm>John doe</Nm>"
+ " <Id>"
+ " <OrgId>"
+ " <Othr>"
+ " <Id/>"
+ " </Othr>"
+ " </OrgId>"
+ " </Id>"
+ "</Dbtr>";
while (true) {
String repl = xml.replaceAll("<(\\w+)>\\s*</\\1>|<\\w+/>", "");
if (repl.length() == xml.length())
break;
xml = repl;
}
System.out.println(xml);
// -> <Dbtr> <Nm>John doe</Nm> </Dbtr>

How to read namespace as it is in a xml using XMLStreamReader?

I have an xml file from which i read using an XMLStreamReader object.
So i'll keep it simple :
Let's take this xml example :
<mySample xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attribute1="value1"/>
So what i need is to get the value (as a String) "xmlns:xsi" and get the value (as a String also) "http://www.w3.org/2001/XMLSchema-instance"
I did try to have a test like this :
if (reader.getEventType() != XMLStreamConstants.NAMESPACE){
attributeName = reader.getAttributeLocalName(i);
attributeValue = reader.getAttributeValue(i);
}
else{
attributeName = reader.getNamespacePrefix(i) + reader.getNamespaceURI(i);
attributeValue = reader.getAttributeValue(i);
}
But it did not work.
Obviously i missed something being a newbie to this API, so any help would be very welcome.
The JSR-173 specification (Stax API for Java) states the following regarding the NAMESPACE event :
Namespace
Namespace declarations can also exist outside of a StartElement and may be reported as a
standalone information item. In general Namespaces are reported as part of a StartElement
event. When namespaces are the result of an XQuery or XPath expression they may be
reported as standalone events.
So if you are looking at namespace events, you should most probably be checking StartElement events, and inspect them. Once again, from the spec :
Namespaces can be accessed using the following methods:
int getNamespaceCount();
String getNamespacePrefix(int index);
String getNamespaceURI(int index);
Only the namespaces declared on the current StartElement are available. The list does
not contain previously declared namespaces and does not remove redeclared namespaces.
At any point during the parsing, you can get the current complete namespace context :
The namespace context of the current state is available by calling
XMLStreamReader.getNamespaceContext() or
StartElement.getNamespaceContext(). These methods return an instance of the
javax.xml.namespace.NamespaceContext interface.
That's theory : most namespace declarations come from START_ELEMENT, some may come independently.
In practice, I have never came accross a NAMESPACE event reported by the API when reading from a file. It's almost always reported as part of a START_ELEMENT (and repeated in the corresponding END_ELEMENT), so you must check START_ELEMENT if you are interested in namespace declaration. For example, starting with your document :
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><mySample xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" attribute1=\"value1\"/>";
XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(new StringReader(xml));
while (reader.hasNext()) {
int event = reader.next();
if (XMLStreamConstants.START_ELEMENT == event) {
if (reader.getNamespaceCount() > 0) {
// This happens
System.out.println("ELEMENT START: " + reader.getLocalName() + " , namespace count is: " + reader.getNamespaceCount());
for (int nsIndex = 0; nsIndex < reader.getNamespaceCount(); nsIndex++) {
String nsPrefix = reader.getNamespacePrefix(nsIndex);
String nsId = reader.getNamespaceURI(nsIndex);
System.out.println("\tNamepsace prefix: " + nsPrefix + " associated with URI " + nsId);
}
}
} else if(XMLStreamConstants.NAMESPACE == event) {
// This almost never happens
System.out.println("NAMESPACE EVENT");
}
}
Will produce :
ELEMENT START: mySample , namespace count is: 1
Namepsace prefix: xsi associated with URI http://www.w3.org/2001/XMLSchema-instance
Bottom line : you should check for NAMESPACE and START_ELEMENT events, even if most of times, you will only have START_ELEMENT reporting namespace declartions, it is not one or the other, it's both.

Bug reading CDATA from xml element in Java

been scratching my head for a while here...
So I have a Java application. In this application I need to read an XML file, get the Character Data from an element, pass it into a new DOM Document, change some of the elements, and convert the new Document back into CDATA, reattach it to the original message and send it off.
So... Here is the message I need to read in, and the function which reads it in:
private static String getCharacterDataFromElement(Node e) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
System.out.println(cd.getBaseURI());
System.out.println(cd.getData());
return cd.getBaseURI();
}
return "error...";
}
And here is the xml file which needs to be changed
<RLSOLVE_MSG version="5.0">
<MESSAGE>
<SOURCE_ID>DP01</SOURCE_ID>
<TRANS_NUM>000001</TRANS_NUM>
</MESSAGE>
<POI_MSG type="interaction">
<INTERACTION name="posPrintReceipt">
<RECEIPT type="merchant" format="xml">
<![CDATA[<RECEIPT>
<AUTH_CODE>06130</AUTH_CODE>
<CARD_SCHEME>VISA</CARD_SCHEME>
<CURRENCY_CODE>GBP</CURRENCY_CODE>
<CUSTOMER_PRESENCE>internet</CUSTOMER_PRESENCE>
<FINAL_AMOUNT>1.00</FINAL_AMOUNT>
<MERCHANT_NUMBER>8888888</MERCHANT_NUMBER>
<PAN_NUMBER>454420******0382</PAN_NUMBER>
<PAN_EXPIRY>12/15</PAN_EXPIRY>
<TERMINAL_ID>04176421</TERMINAL_ID>
<TOKEN>454420bbbbbkqrm0382</TOKEN>
<TOTAL_AMOUNT>1.00</TOTAL_AMOUNT>
<TRANSACTION_DATA_SOURCE>keyed</TRANSACTION_DATA_SOURCE>
<TRANSACTION_DATE>14/02/2014</TRANSACTION_DATE>
<TRANSACTION_NUMBER>000001</TRANSACTION_NUMBER>
<TRANSACTION_RESPONSE>06130</TRANSACTION_RESPONSE>
<TRANSACTION_TIME>17:13:17</TRANSACTION_TIME>
<TRANSACTION_TYPE>purchase</TRANSACTION_TYPE>
<VERIFICATION_METHOD>unknown</VERIFICATION_METHOD>
<DUPLICATE>false</DUPLICATE>
</RECEIPT>]]>
</RECEIPT>
</INTERACTION>
</POI_MSG>
</RLSOLVE_MSG>
When cd.getData() is executed, it returns "\n \t \t \t \t"
Aaaany ideas?
Look closely at your XML. If I write them in one line it's actually
<RECEIPT type="merchant" format="xml">\n\t\t\t<![CDATA[...]]>\n\t\t\t</RECEIPT>
So the tree will actually look something like:
RECEIPT
/ | \
\n\t\t\t CDATA \n\t\t\t
So you got three children. As you are only getting the first child, you're only getting \n\t\t\t.
Loop through all the children and concat their data and you should have everything.

Error when using xmlstream reader

I am using xmlstreamreader in java to read attribute values and other data. This is the xml String:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><samlp:AuthnReques
t xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL
="http://localhost:8080/consumer.jsp" **ID="abc"** **IssueInstant="2012-04-14T11:44:49
:796"** ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="
2.0">**<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://loca
lhost:8080/saml/SProvider.jsp</saml:Issuer>**<Signature xmlns="http://www.w3.org/2
000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.or
g/2001/10/xml-exc-c14n#WithComments"/><SignatureMethod Algorithm="http://www.w3.
org/2000/09/xmldsig#rsa-sha1"/><Reference URI=""><Transforms><Transform Algorith
m="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestM
ethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><DigestValue>VzKYOu1g
ert3DDrNUSO1/Au3PGeD1PEyPuJeI2GO6ec=</DigestValue></Reference></SignedInfo><Sign
atureValue>k7hVlbsEhGW5ryelSbrwWWyJq3cdyDuVeQCOqRilbky8hEk/1sHI9DNOvOlPZ7OC9bI4d
EHm46R1
CDXoXkyOoXdq+3M/HbUakHM7eNvF5+j+NUXUX9dijb/rDzq05VNHcSIDXRpvMc1IRBremi0voVqX
ZuHRn+IBeD8hSK1LXsE=</SignatureValue></Signature></samlp:AuthnRequest>
Then I tried to read the attribute ID, IssueInstant and the element Issuer. all the 3 are highlighted(actually between **) in the above string. I have used the following code:
while(reader.hasNext()){
reader.next();
if(reader.getEventType() == XMLStreamReader.START_ELEMENT){
if(reader.getLocalName().equals("AuthnRequest"))
{
String ns=reader.getNamespaceURI();
System.out.println(ns);
id=reader.getAttributeValue(ns,"ID");
rec_instant=reader.getAttributeValue(ns,"IssueInstant");
System.out.println("1"+id);
System.out.println("2"+rec_instant);
}
else if(reader.getLocalName().equals("Issuer"))
{
rec_issuer=reader.getElementText();
System.out.println("4"+reader.getElementText());
}
}
}
But I am getting the folowing output:
1null
2null
javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,436]
Message: parser must be on START_ELEMENT to read next text
What is the issue?
You are using ns for the attributes, but the attributes are in fact in the null ns (they have no namespace). As for the exception, you are calling getElementText twice. This method is not a pure getter, it also advances the reader to the end element (as per its Javadoc).
As Marko suggests, the exception is due to calling getElementText() twice in a row.
If I change this:
String rec_issuer=reader.getElementText();
System.out.println("4"+reader.getElementText());
to this:
String rec_issuer = reader.getElementText();
System.out.println("4" + rec_issuer);
then I get the following output:
urn:oasis:names:tc:SAML:2.0:protocol
1null
2null
4http://localhost:8080/saml/SProvider.jsp
If I also change the getAttributeValue calls to use null instead of ns, like this:
String id = reader.getAttributeValue(null,"ID");
String rec_instant = reader.getAttributeValue(null,"IssueInstant");
I get:
urn:oasis:names:tc:SAML:2.0:protocol
1abc
22012-04-14T11:44:49:796
4http://localhost:8080/saml/SProvider.jsp
That's using your original XML.

Categories