try {
DocumentBuilder builder=factory.newDocumentBuilder();
Document doc = builder.parse("15122021.xml");
NodeList currencyList= doc.getElementsByTagName("Currency");
for(int i=0;i<currencyList.getLength();i++){
Node p = currencyList.item(i);
if(p.getNodeType()==Node.ELEMENT_NODE){
Element mainTag = (Element) p;
NodeList currencySellPriceList= mainTag.getElementsByTagName("ForexSelling");
NodeList currencyBuyPriceList = mainTag.getElementsByTagName("ForexBuying");
NodeList currencyNameList2= mainTag.getElementsByTagName("CurrencyName");
for(int j=0;j<currencyNameList2.getLength();j++){
Node c=currencyNameList2.item(j);
Node cbp=currencyBuyPriceList.item(j);
Node csp=currencySellPriceList.item(j);
if(c.getNodeType()==Node.ELEMENT_NODE && cbp.getNodeType()==Node.ELEMENT_NODE && csp.getNodeType()==Node.ELEMENT_NODE){
System.out.println("Currency name: "+c.getTextContent());
System.out.println("Buy price: "+cbp.getTextContent());
System.out.println("Sell price: "+csp.getTextContent());
}
}
}
}
} catch (ParserConfigurationException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
} catch (SAXException e) {
System.out.println(e.getMessage());
}
I am trying to parse XML file like this in main method and it works.But when i try to take this code block to another method like this
public class XMLScraperBuilder {
public NodeList getBuyPrices() throws IOException, SAXException, ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
NodeList currencySellPriceList=null;
DocumentBuilder builder=factory.newDocumentBuilder();
Document doc = builder.parse("15122021.xml");
NodeList currencyList= doc.getElementsByTagName("Currency");
for(int i=0;i<currencyList.getLength();i++){
Node currency = currencyList.item(i);
if(currency.getNodeType()==Node.ELEMENT_NODE){
Element mainTag = (Element) currency;
currencySellPriceList= mainTag.getElementsByTagName("ForexSelling");
for(int j=0;j<currencySellPriceList.getLength();j++){
Node c = currencySellPriceList.item(j);
}
}}
return currencySellPriceList;
}}
It returns nothing when i try to print the NodeList with a for loop in my main method(after creating an object from XMLScraperBuilder).Any ideas?
Related
I have a use case where my XML is like this
<IR>
<name>abc</name>
<Level></Level>
</IR>
<IR>
<name>xyz</name>
<Level>LVL00006</Level>
</IR>
I am using below code to extract information of level.
public class TestUseCases {
public static void main(String[] args) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
} catch (ParserConfigurationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Document document;
try {
document = factory.newDocumentBuilder()
.parse(new InputSource(new StringReader(xml)));
String xpathExpression = "";
Map<String, List<String>> iRValues = new LinkedHashMap<String, List<String>>();
xpathExpression = "(/IR/Level/text())";
iRValues.put("REQLVL", evaluateXPath(document, xpathExpression));
System.out.println(iRValues);
} catch (SupportException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException | IOException | ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static List<String> evaluateXPath(Document document, String xpathExpression) throws SupportException {
// Create XPathFactory object
XPathFactory xpathFactory = XPathFactory.newInstance();
// Create XPath object
XPath xpath = xpathFactory.newXPath();
List<String> values = new ArrayList<>();
try {
// Create XPathExpression object
XPathExpression expr = xpath.compile(xpathExpression);
// Evaluate expression result on XML document
NodeList nodes = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
System.out.println(nodes.getLength());
for (int i = 0; i < nodes.getLength(); i++) {
String item = nodes.item(i).getNodeValue();
System.out.println(item);
if (item.trim().isEmpty()) {
values.add(SupportConstants.EMPTY_SPACE);
} else {
values.add(nodes.item(i).getNodeValue());
}
}
} catch (XPathExpressionException e) {
throw new SupportException(SupportExceptionMessage.ERROR_IN_READING_RESPONSE_FROM_CM);
}
return values;
}
}
OUTPUT:
1
LVL00006
{REQLVL=[LVL00006]}
The problem is because first level tag is empty, I get a list which has only one element and I am not able to know whether the element is of abc or xyz. Is there a way so that I can put space if the tag is empty?
I am expecting list as [" ", LVL00006].
public void loadSettings() {
try {
File inputFile = new File("data.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("Setting");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nList.item(temp);
NodeList VariableName = eElement.getElementsByTagName("VariableName");
NodeList VariableValue = eElement.getElementsByTagName("VariableValue");
System.out.println(VariableName.item(0).getTextContent());
if (VariableName.item(0).hasChildNodes()) {
}
// txtBookmarkUrl.setText(bookMarkUrl);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
I want to make a function that gets second part of the xml in settings elements. I want the function to return a result so that i can assign it to textfield default value when the swing GUI starts. The function should take let's say 'isDecaptcher' variable name and return '0' VariableValue.
<Bookmark>
<Setting>
<VariableName>isDeathbycaptcha</VariableName>
<VariableValue>0</VariableValue>
</Setting>
<Setting>
<VariableName>isDecaptcher</VariableName>
<VariableValue>0</VariableValue>
</Setting>
<Setting>
<VariableName>isExpertdecoders</VariableName>
<VariableValue>0</VariableValue>
</Setting>
<Setting>
<VariableName>ManualCaptcha</VariableName>
<VariableValue>1</VariableValue>
</Setting>
</Bookmark>
public void loadSettings(String variableName) {
try {
File inputFile = new File("data.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("Setting");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nList.item(temp);
NodeList VariableName = eElement.getElementsByTagName("VariableName");
NodeList VariableValue = eElement.getElementsByTagName("VariableValue");
if (VariableName.item(0).getTextContent().equalsIgnoreCase(variableName)) {
String txtBookmarkUrlValue = VariableValue.item(0).getLastChild().getTextContent();
System.out.println(txtBookmarkUrlValue);
txtBookmarkUrl.setText(txtBookmarkUrlValue);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
This works, But if you have more robust answers you can share.
First of all create an Object wich will represent your settings. The case is to reuse it's values in whole app. I assume that you will use it only once at the beginning and settings will not change. Singleton pattern would fit there.
final class Settings{
private static volatile Settings instance = null;
private boolean _isDeathByCaptcha;
private boolean _manualCaptcha;
...
//getters & setters
public boolean isDeathByCaptcha(){
return _isDeathByCaptcha;
}
public void setIsDeathByCaptcha(boolean isDeathByCaptcha){
this._isDeathByCaptcha = isDeathByCaptcha;
}
private Settings(){}
public static Settings getInstance(){
if(instance == null){
synchronized (Settings.class) {
if (instance == null) {
instance = new Settings();
}
}
}
return instance;
}
}
After that you can call Settings.getInstance().isDeathByCaptcha(); to get your value. Of course you need to set it earlier with setter.
I am making some changes to an embedded XML file in my Java application. I have some fields, a LOAD button and a SAVE button. After clicking the save button I can see the XML file updating, but after clicking the load button the old values are being loaded to the fields.
Here is my code:
public class MyLoad_SaveSampleProject {
public String field1 = "";
public String field2 = "";
public void loadSampleProject() {
InputStream file = MyLoad_SaveSampleProject.class.getResourceAsStream("/main/resources/otherClasses/projects/SampleProject.xml");
try {
DocumentBuilderFactory DocBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder DocBuilder = DocBuilderFactory.newDocumentBuilder();
Document Doc = DocBuilder.parse(file);
NodeList list = Doc.getElementsByTagName("*"); //create a list with the elements of the xml file
for (int i=0; i<list.getLength(); i++) {
Element element = (Element)list.item(i);
if (element.getNodeName().equals("field1")) {
field1 = element.getChildNodes().item(0).getNodeValue().toString();
} else if (element.getNodeName().equals("field2")) {
field2 = element.getChildNodes().item(0).getNodeValue().toString();
}
}
} catch (Exception e) {
System.out.println(e);
}
}
public void saveSampleProject(String field1Str, String field2Str) {
InputStream file = MyLoad_SaveSampleProject.class.getResourceAsStream("/main/resources/otherClasses/projects/SampleProject.xml");
try {
DocumentBuilderFactory DocBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder DocBuilder = DocBuilderFactory.newDocumentBuilder();
Document Doc = DocBuilder.parse(file);
NodeList list = Doc.getElementsByTagName("*"); //create a list with the elements of the xml file
for (int i=0; i<list.getLength(); i++) {
Node thisAttribute = list.item(i);
if (thisAttribute.getNodeName().equals("field1")) {
thisAttribute.setTextContent(field1Str);
} else if (thisAttribute.getNodeName().equals("field2")) {
thisAttribute.setTextContent(field2Str);
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(Doc);
StreamResult result = new StreamResult(new File("src/main/resources/otherClasses/projects/SampleProject.xml"));
transformer.transform(source, result);
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (SAXException sae) {
sae.printStackTrace();
}
}
public String returnField1() {
return field1;
}
public String returnField2() {
return field2;
}
}
And this is my default XML file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><Strings>
<field1>string1</field1>
<field2>string2</field2>
</Strings>
When the save button is pressed I am using the saveSampleProject method. When the load button is pressed I am using the loadSampleProject method and then I am getting the field values with the returnField1 and returnField2 methods.
I have no idea of what could be wrong with what I'm doing. I would appreciate any suggestions.
Most probably that calling method getResourceAsStream() leads to resource caching. Since you are using File() in save method try to get InputStream on data load using File object, and not as resource.
I am trying to read from xml file but I get a null pointer exception.
this is the xml file:
<war>
<missileLaunchers>
<launcher id="L101" isHidden="false">
<missile id="M1" destination="Sderot" launchTime="2" flyTime="12" damage="1500"/>
<missile id="M2" destination="Beer-Sheva" launchTime="5" flyTime="7" damage="2000"/>
</launcher>
<launcher id="L102" isHidden="true">
<missile id="M3" destination="Ofakim" launchTime="4" flyTime="3" damage="5000"/>
<missile id="M4" destination="Beer-Sheva" launchTime="9" flyTime="7" damage="1000"/>
</launcher>
</missileLaunchers>
<missileDestructors >
<destructor id="D201">
<destructdMissile id="M1" destructAfterLaunch="4"/>
<destructdMissile id="M3" destructAfterLaunch="7" />
<destructdMissile id="M4" destructAfterLaunch="2"/>
</destructor>
<destructor id="D202">
<destructdMissile id="M2" destructAfterLaunch="3"/>
</destructor>
</missileDestructors>
<missileLauncherDestructors >
<destructor type="plane" >
<destructedLanucher id="L101" destructTime="4"/>
</destructor>
<destructor type="ship">
<destructedLanucher id="L102" destructTime="8" />
<destructedLanucher id="L102" destructTime="12"/>
</destructor>
</missileLauncherDestructors>
</war>
and this is the code:
public class XmlReader
{
File fXmlFile=null;
DocumentBuilderFactory dbFactory=null;
DocumentBuilder dBuilder=null;
Document doc=null;
public XmlReader(String filePath) throws ClassNotFoundException
{
if(filePath!=null)
{
this.fXmlFile = new File(filePath);
dbFactory = DocumentBuilderFactory.newInstance();
try {
dBuilder = dbFactory.newDocumentBuilder();
} catch (ParserConfigurationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
} catch (SAXException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else System.out.println("Xml file not found");
}
//gets value by tag name
private static String getTagValue(String tag, Element element) {
if(element.hasChildNodes())
{
NodeList nodeList = element.getElementsByTagName(tag).item(0).getChildNodes();
Node node = (Node) nodeList.item(0);
if(node==null)
return null;
return node.getNodeValue();
}
else return element.getNodeValue();
}
//launcher
public List<Launcher> readLauncher() throws Exception
{
List<Launcher> launcherList = new ArrayList<Launcher>();
try
{
NodeList nList = doc.getElementsByTagName("launcher");
for(int i=0;i<nList.getLength();i++)
{launcherList.add(getLauncher(nList.item(i)));}
}
catch (Exception e)
{
e.printStackTrace();
}
return launcherList;
}
//builds the object
private static Launcher getLauncher(Node node)
{
//XMLReaderDOM domReader = new XMLReaderDOM();
Launcher launcher = new Launcher();
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element element = (Element) node;
// launcher.setIsHidden(Boolean.parseBoolean(getTagValue("isHidden", element)));
// launcher.setId(getTagValue("id", element));
System.out.println("id = "+getTagValue("id", element));
System.out.println("ishidden = "+getTagValue("isHidden", element));
}
return launcher;
}
}
And this is the stack trace:
java.lang.NullPointerException
at XmlReader.getTagValue(XmlReader.java:56)
at XmlReader.getLauncher(XmlReader.java:96)
at XmlReader.readLauncher(XmlReader.java:78)
at Program.main(Program.java:27)
I can not change the format of the xml file.
It seems to fail when it tries to get the actual value of the node's fields or so I assume.
Though I don;t understand the reason...when I check the size of the node list it turns fine it does give me 2.
The problem is below line:
System.out.println("id = " + getTagValue("id", element));
where getTagValue("id", element) is calling
NodeList nodeList = element.getElementsByTagName(tag).item(0).getChildNodes();
Here element.getElementsByTagName("id") will return null
It should be get from attribute
// gets value by tag name
private static String getTagValue(String tag, Element element) {
return element.getAttributeNode(tag).getValue();
}
You are calling getElementsByTagName() in getTagValues, however you are trying to retrieve attributes of the tag. You may need to call getAttribute() instead. For Example:
element.getAttribute(attributeName)
where attributeName is "id" or "isHidden". This will return the value as a String and can be returned directly with no further processing.
I'm getting some attributes from a complex XML file:
<rsp>
<csl d='10775.916760613756' id='2003' nam='AUTOS TEZIUTLÁN, S.A. DE C.V.'
adr='KM. 1 CARR. TEZIUTLÁN-TLAPACOYAN' tel='231312-12-05'
lat='19.826765' lon='-97.347906' />
<csl d='10789.680721293766' id='2019' nam='AUTOMOVILÍSTICA DE TEHUACAN, S.A. DE C.V.'
adr='BLVD. ADOLFO LOPEZ MATEOS NO. 3623' tel='238382-44-33'
lat='18.467281' lon='-97.417901' />
<csl d='10848.586325071066' id='2013' nam='AUTOMOTRIZ DE LA SIERRA, S.A. DE C.V.'
adr='AUSENCIO T. JIMÉNEZ No. 1' tel='776762-05-42'
lat='20.174386' lon='-98.06125' />
<csl d='10866.815936520663' id='2028' nam='MOTORES ALEMANES RIVERA S.A. DE C.V.'
adr='CALZADA IGNACIO ZARAGOZA NO. 180' tel='222286-02-02'
lat='19.064258' lon='-98.179042' />
<csl d='10867.374198658401' id='2012' nam='ARMENTA AUTOMOTRIZ, S.A. DE C.V.'
adr='24 NORTE No. 214' tel='222235-87-68'
lat='19.038912' lon='-98.183101' />
</rsp>
But my XQUERY only gives me the first attribute and only that using this class:
public class XMLParser {
private String[] resultTable;
public XMLParser(){}
public String[] stringToXML(String xmlString) {
try{
DocumentBuilderFactory dBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dBuilderFactory.newDocumentBuilder();
InputSource iSource = new InputSource();
iSource.setCharacterStream(new StringReader(xmlString));
Document doc = dBuilder.parse(iSource);
NodeList nList = doc.getElementsByTagName("tpr");
resultTable = new String [nList.getLength()];
for (int i=0; i<nList.getLength(); i++){
Element e = (Element)nList.item(i);
NodeList pCode = e.getElementsByTagName("tpr");
Element line = (Element)pCode.item(0);
resultTable[i] = getCharacterDataFromElement(line);
}
}
catch(Exception e) {
e.printStackTrace();
}
return resultTable;
}
public static String getCharacterDataFromElement(Element e) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cData = (CharacterData) child;
return cData.getData();
}
return "null";
}
public static String getParamByXPath(String xmlString, String expression) {
String ret = "";
XPath xpath = XPathFactory.newInstance().newXPath();
try{
DocumentBuilderFactory dBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dBuilderFactory.newDocumentBuilder();
InputSource iSource = new InputSource();
iSource.setCharacterStream(new StringReader(xmlString));
Document doc = dBuilder.parse(iSource);
XPathExpression exp = xpath.compile(expression);
Object result = exp.evaluate(doc);
if (result instanceof String) ret = (String)result;
else if (result instanceof Boolean) ret = result.toString();
else if (result instanceof Double) ret = result.toString();
else if (result instanceof NodeList) {
NodeList list = (NodeList) result;
Node node = list.item(0);
Log.d("LIST", Integer.toString(list.getLength()));
ret = node.getTextContent();
}
}catch(Exception e) {
e.printStackTrace();
}
return ret;
}
I'm invoking the method with this line:
String loc1 = XMLParser.getParamByXPath(service, "//#d");
I have been using other Querys, but the result is always the first element... what could I be missing?
The //#d XPath will return a list of all #d attribute nodes in your document.
Your Java code:
else if (result instanceof NodeList) {
NodeList list = (NodeList) result;
Node node = list.item(0); // <-- THIS ONE HERE
Log.d("LIST", Integer.toString(list.getLength()));
ret = node.getTextContent();
}
will then take the first one (list.item(0)) and that's what you're getting.
It looks like your "issue" is with the Java logic, not the XPath.