So i am trying to replace the values of username and password in the XML file containing a SOAP message. Here are the elements:
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken u:Id="uuid-68f84594-d592-470b-9bbc-b29f58b4756f-1">
<o:Username></o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"></o:Password>
</o:UsernameToken>
</o:Security>
Basically, i want to take the username and password values from my config file, and place them in the username and password fields within the XML file containing the soap message. This is my attempt, and it throws a NPE at the docElement.getElementsByTagName lines:
public void updateUserDetails() {
final Properties configProperties = new Properties();
try {
configProperties.load(new FileInputStream(PROPERTIES));
final Document requestDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream(SOAP_REQUEST));
final Element docElement = requestDoc.getDocumentElement();
docElement.getElementsByTagName("Username").item(0).setTextContent(configProperties.getProperty("username"));
docElement.getElementsByTagName("Password").item(0).setTextContent(configProperties.getProperty("password"));
} catch(IOException | ParserConfigurationException | SAXException exception) {
LOGGER.error("There was an error loading the properties file", exception);
}
}
Any help will be appreciated!
It seems to be related to a namespace problem.
Try specifying the namespace for your tag:
String namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
final Document requestDoc = factory.newDocumentBuilder().parse(new FileInputStream(SOAP_REQUEST));
docElement.getElementsByTagNameNS(namespace, "Username").item(0).setTextContent(configProperties.getProperty("username"));
docElement.getElementsByTagNameNS(namespace, "Password").item(0).setTextContent(configProperties.getProperty("password"));
Also, don't forget in the end to write the result back to file:
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource domSource = new DOMSource(requestDoc);
StreamResult streamResult = new StreamResult(new File(SOAP_REQUEST));
transformer.transform(domSource, streamResult);
Related
In a xsl transformation I have a xslt file that includes some other xslt. The problem is that the URI for these xslt contains illegal characters, in particular '##'. The xslt looks like this:
<xsl:include href="/appdm/tomcat/webapps/sentys##1.0.0/WEB-INF/classes/xslt/release_java/xslt/gen.xslt" />
and when I try to instantiate a java Transformer I get the error:
javax.xml.transform.TransformerConfigurationException: javax.xml.transform.TransformerConfigurationException: javax.xml.transform.TransformerException: org.xml.sax.SAXException: org.apache.xml.utils.URI$MalformedURIException: Fragment contains invalid character:#
This is the java code:
public String xslTransform2String(String sXml, String sXslt) throws Exception {
String sResult = null;
try {
Source oStrSource = createStringSource(sXml);
DocumentBuilderFactory oDocFactory = DocumentBuilderFactory.newInstance();
oDocFactory.setNamespaceAware(true);
//sXslt is the xslt content with the inclusions
//<xsl:include href="/appdm/tomcat/webapps/sentys##1.0.0/WEB-INF/classes/xslt/release_java/xslt/gen.xslt" />"
Document oDocXslt = oDocFactory.newDocumentBuilder().parse(new InputSource(new StringReader(sXslt)));
Source oXsltSource = new DOMSource(oDocXslt);
StringWriter oStrOut = new StringWriter();
Result oTransRes = createStringResult(oStrOut);
Transformer oTrans = createXsltTransformer(oXsltSource);
oTrans.transform(oStrSource, oTransRes);
sResult = oStrOut.toString();
} catch (Exception oEx) {
throw new BddException(oEx, XmlProvider.ERR_XSLT, null);
}
return sResult;
}
private Transformer createXsltTransformer(Source oXsltSource) throws Exception {
Transformer transformer = getXsltTransformerFactory().newTransformer(
oXsltSource);
ErrorListener errorListener = new DefaultErrorListener();
transformer.setErrorListener(errorListener);
return transformer;
}
is there a way I can go with relative paths instead of absolute path?
Thank you
To avoid the MalformedURIException, replace the second or both # with %23.
See https://stackoverflow.com/a/5007362/4092205
I have written a program to find all XML files matching a particular pattern in a directory and modify it by adding a new tag.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<paths>
<upgradepath startversion="1.4.0.0" moduleid="${moduleId}" endversion="1.4.0.1">
<steps>
<!-- Put scripts here to go from 1.4.0.0 to 1.4.0.1 -->
</steps>
</upgradepath>
<upgradepath startversion="1.4.0.1" moduleid="${moduleId}" endversion="1.4.0.2">
<steps>
<!-- Put scripts here to go from 1.4.0.1 to 1.4.0.2 -->
</steps>
</upgradepath>
</paths>
After running my program the XML file gets modified as below :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<paths>
<upgradepath endversion="1.4.0.1" moduleid="${moduleId}" startversion="1.4.0.0">
<steps>
<!-- Put scripts here to go from 1.4.0.0 to 1.4.0.1 -->
</steps>
</upgradepath>
<upgradepath endversion="1.4.0.2" moduleid="${moduleId}" startversion="1.4.0.1">
<steps>
<!-- Put scripts here to go from 1.4.0.1 to 1.4.0.2 -->
</steps>
</upgradepath>
<upgradepath endversion="1.4.0.3" moduleid="${moduleId}" startversion="1.4.0.2">
<steps>
<!--Put scripts here to go from 1.4.0.2 to 1.4.0.3-->
</steps>
</upgradepath>
</paths>
If you see the attributes of all the tags you will see that they have all been rearranged in ascending order. The startversion attribute now appears last and the endversion attribute appears first. I want the original order of the attributes after modification of the XML file. I have tried almost everything and have lost all hope. Is there any way I can do this? Also is there a way to sort the attributes in descending order? It's not the right solution but it helps.
Here is a code snippet from the program I am using to modify the files :
private static void updateXMLFiles(String sStartVersion, String sEndVersion) {
try {
for (int c = 0; c < pathsList.size(); c++) {
File xmlFile = new File(pathsList.get(c).toString());
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
doc.getDocumentElement().normalize();
// Get the last <upgradepath> tag in the file.
// Method Call to verify the version entered and update the XML Files.
// Write the updated document to the file.
doc.getDocumentElement().normalize();
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(pathsList.get(c).toString()));
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(source, result);
}
catch (SAXException e1) {
e1.printStackTrace();
}
catch (ParserConfigurationException e1) {
e1.printStackTrace();
}
catch (IOException e1) {
e1.printStackTrace();
}
catch (TransformerException e1) {
e1.printStackTrace();
}
}
private static void addNewVersion(Document doc, String sStartVersion, String sEndVersion) {
Element element = doc.getDocumentElement();
Element upgradePath = doc.createElement("upgradepath");
upgradePath.setAttribute("startversion", sStartVersion);
upgradePath.setAttribute("moduleid", "${moduleId}");
upgradePath.setAttribute("endversion", sEndVersion);
Element steps = doc.createElement("steps");
Comment comment = doc.createComment("Put scripts here to go from " + sStartVersion + " to " + sEndVersion);
steps.appendChild(comment);
upgradePath.appendChild(steps);
element.appendChild(upgradePath);
}
Is there any way I can keep the order of the attributes intact or in the worst case arrange it in descending order?
A friend of mine suggested I try out JAXB but I couldn't find a way to achieve this. If someone thinks JAXB can solve this do mention how to format an existing XML file and not creating one.
Another issue which is not a major concern is that although I have used the
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
the newly added tags are not indented correctly. Any way to fix this?
#XmlType(propOrder = {"startversion", "moduleid", "endversion", "steps"})
public class XmlSubModel {
private String startversion = "";
private String moduleid = "";
private String endversion = "";
private String steps = "";
#XmlAttribute
public String getStartversion() {
return startversion;
}
public void setStartversion(String startversion) {
this.startversion = startversion;
}
#XmlAttribute
public String getModuleid() {
return moduleid;
}
public void setModuleid(String moduleid) {
this.moduleid = moduleid;
}
#XmlAttribute
public String getEndversion() {
return endversion;
}
public void setEndversion(String endversion) {
this.endversion = endversion;
}
public String getSteps() {
return steps;
}
public void setSteps(String steps) {
this.steps = steps;
}
}
I am trying to send xml file to server after processing it which has some special character like "佥佬佧佼A£".
Currently code looks like
public class Utils {
public static String transformToString(Document activeDocument) throws TransformerException{
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "true");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(document), new StreamResult(writer));
writer.toString();
}
Test class
public class Test {
public static void main(String[] args){
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlPath);
//Doing some process on doc and changing other values
String xmlString = Utils.transformToString(doc);
// Sending xml to soap
HttpPost post = new HttpPost(endpoint);
post.setEntity(new StringEntity(xmlString));
post.setHeader(new BasicHeader("content-type", "text/xml"));
.................
}
}
XML file
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope ....>
<soapenv:Header/>
<soapenv:Body>
<Test>
<Id>佥佬佧佼A£</Id>
..............
..........
</Test>
.........
I am getting xmlString with Id value : ????A£
What I want is : 佥佬佧佼A£
How can I do that ? I just want String format of that XML.
EDIT : I am loading one XML, Doing some changes into it, and sending that XML to SOAP, by Setting that document to httpPost.setEntity()
Thanks,
Ankit
You can try:
encoding="UTF-16"
instead of
encoding="UTF-8"
I have a xml file which is a response from Webservice.It has got various namespaces involved with it. When I try to validate it with appropriate XSD its throwing "org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'SOAP-ENV:Envelope'." The namespace declaration for all the namespaces are declared in the response.
Following is my code
try {
DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance();
SchemaFactory schemaFactory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
SAXSource mainInputStream = new SAXSource(new InputSource(new FileInputStream(new File("FIXEDINCOME_v3_0.xsd"))));
SAXSource importInputStream1 =new SAXSource(new InputSource(new FileInputStream(new File("Rating.xsd"))));
SAXSource importInputStream2 = new SAXSource(new InputSource(new FileInputStream(new File("Datatypes.xsd"))));
Source[] sourceSchema = new SAXSource[]{mainInputStream , importInputStream1, importInputStream2};
Schema schema = schemaFactory.newSchema(sourceSchema);
xmlFact.setNamespaceAware(true);
xmlFact.setSchema(schema);
DocumentBuilder builder = xmlFact.newDocumentBuilder();
xmlDOC = builder.parse(new InputSource(new StringReader(inputXML)));
NamespaceContext ctx = new NamespaceContext() {
public String getNamespaceURI(String prefix) {
String uri;
if (prefix.equals("ns0"))
uri = "http://namespace.worldnet.ml.com/EDS/Standards/Common/Service_v1_0/";
else if (prefix.equals("ns1"))
uri = "http://namespace.worldnet.ml.com/EDS/Product/Services/Get_Product_Data_Svc_v3_0/";
else if (prefix.equals("ns2"))
uri = "http://namespace.worldnet.ml.com/DataSOA/Product/Objects/FixedIncome/FixedIncome_v3_0/";
else if (prefix.equals("ns3")) {
uri = "http://namespace.worldnet.ml.com/DataSOA/Product/Objects/Rating/Rating_v2_0/";
} else if (prefix.equals("SOAP-ENV")) {
uri = "http://schemas.xmlsoap.org/soap-envelope/";
} else
uri = null;
return uri;
}
// Dummy implementation - not used!
public Iterator getPrefixes(String val) {
return null;
}
// Dummy implemenation - not used!
public String getPrefix(String uri) {
return null;
}
};
XPathFactory xpathFact = XPathFactory.newInstance();
xPath = xpathFact.newXPath();
xPath.setNamespaceContext(ctx);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I don't think the problem is with detecting the namespace definition for the SOAP-ENV prefix. The validator needs the XSD file that defines elements used in that namespace in order to validate the SOAP-ENV:Envelope element, so you need to tell the validator where that schema is located.
I think the solution is either to add the following to your XML reponse:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://schemas.xmlsoap.org/soap/envelope/"
xsi:schemaLocation="http://schemas.xmlsoap.org/soap/envelope/
http://schemas.xmlsoap.org/soap/envelope/">
Or, go download that schema off the web, save it to your local filesystem as an XSD file, and add it to your sourceSchema array. The first method should be preferred as it leads to more portable code (and XML).
Have you tried using the following URI for the SOAP-ENV?
http://schemas.xmlsoap.org/soap/envelope/
The set of schemas you are providing for validation does not include the soap schema. you can either include the soap schema in the schema collection, or, if you don't care about validating the soap wrapper, just grab the actual body content element and run your validation from there.
I am working on a android(2.2) project which needs xsl transformation. The below code works perfectly in a regular non-android java project
public static String transform() throws TransformerException {
Source xmlInput = new StreamSource(new File("samplexml.xml"));
Source xslInput = new StreamSource(new File("samplexslt.xslt"));
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(xslInput);
OutputStream baos = new ByteArrayOutputStream();
Result result = new StreamResult(baos);
transformer.transform(xmlInput, result);
return baos.toString();
}
I need similar functionality on android. For this I created 2 files under resources/raw:
samplexml.xml
samplexslt.xslt
(contents of these files come from here.
I tried the below code & it does not work (note the StreamSource constructor arg):
public static String transform() throws TransformerException {
TransformerFactory factory = TransformerFactory.newInstance();
Source xmlInput = new StreamSource(this.getResources().openRawResource(R.raw.samplexml));
Source xslInput = new StreamSource(this.getResources().openRawResource(R.raw.samplexslt));
Transformer transformer = factory.newTransformer(xslInput);//NullPointerException here
OutputStream baos = new ByteArrayOutputStream();
Result result = new StreamResult(baos);
transformer.transform(xmlInput, result);
}
I saw the spec & believe I need to set a systemId. But I couldn't get the above code to work.
So, in an android project, how to handle xslt transformations? Please provide your thoughts.
As we know that we Cannot usethisin a static context and you are doing this in your static method transform(). You can do it like this_
public class YourLoadXSLClass extends Activity {
static Resources res;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
res = getResources();
String strHTML = transform();
// Other code.....
}
/*
* Your method that Transform CSLT.
*/
public static String transform() throws TransformerException {
TransformerFactory factory = TransformerFactory.newInstance();
// Now your raw files are accessible here.
Source xmlInput = new StreamSource(
LoadXSLTinWebview.res.openRawResource(R.raw.samplexml));
Source xslInput = new StreamSource(
LoadXSLTinWebview.res.openRawResource(R.raw.samplexslt));
Transformer transformer = factory.newTransformer(xslInput);
OutputStream baos = new ByteArrayOutputStream();
Result result = new StreamResult(baos);
transformer.transform(xmlInput, result);
return baos.toString();
}
}
Here is the complete class code that do the needful. I hope this will help you & all!
I've never done anything with XSLT but, looking at your code, logically there are only two things that could cause an NPE on that line. The first would be that factory might be null but that doesn't make sense.
That leaves xslInput as being the culprit which suggests openRawResource(R.raw.samplexslt) is failing to return a valid InputStream for the StreamSource constructor to use. Try putting a log statement in such as...
if (xslInput != null {
Transformer transformer = factory.newTransformer(xslInput);
...
}
else
Log.d("SomeTAG", "xslInput is null!!!");
If it turns out that xslInput is actually null then it suggests openRawResource(...) can't find/process the .xslt file properly. In that case I'd suggest using AssetManagerto open the .xslt file by name...
AssetManager am = this.getAssets();
Source xslInput = new StreamSource(am.open("samplexslt.xslt"));