How can i modify xml-stylesheet attribute value in java - java

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet href="Sample.xsl" type="text/xsl"?>
<MyDoc>.....</MyDoc>
I want to modify the attribute href's value to 'MyDoc.xsl'. I have tried using XPath but it returns nothing:
//xml-stylesheet[contains(text(), 'Sample.xsl')]/#href";
Also using Document only gives elements starting at MyDoc
NodeList list = taggedC32Doc.getElementsByTagName("*");
Is there any way i can do this?

The line you want to change is a Processing Instruction, not an Element, so neither of your attempts to find it as an element will work. Try
/processing-instruction(xml-stylesheet)
You can then get that node's data, which will be href="Sample.xsl" type="text/xsl". Perform the appropriate string manipulation to find and change the href pseudo-attribute in that string -- sorry, most XML APIs don't provide any assistance in doing so, because as far as XML is concerned the PI's data is an unformatted string even though it's usually structured to resemble attributes -- and set the new data back into the ProcessingInstruction node.

Related

Partial XML parsing giving an element not bound exception

I'm trying to parse an XML document with DSpace XOAI library. This is the input XML:
<?xml version="1.0" encoding="UTF-8"?>
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
...
<ListRecords>
<record>
<header>
...
</header>
<metadata>
<crossref xmlns="http://www.crossref.org/xschema/1.1" xsi:schemaLocation="http://www.crossref.org/xschema/1.1 http://www.crossref.org/schema/unixref1.1.xsd">
...
</crossref>
</metadata>
</record>
</ListRecords>
</OAI-PMH>
From what I could deduce from debugging, each metadata node is parsed individually by XOAI library. And, in that context, I get this error (which makes sense, because the xsi namespace is defined in parent OAI-PMH node):
ERROR: 'The prefix "xsi" for attribute "xsi:schemaLocation" associated with an element type "crossref" is not bound.'
For what I could understand from the library source code, it uses the Oracle java javax.xml.transform.Transformer to make the transformations. We can set any Transformer to be executed.
I'm already using an XSLT file for transforming the input XML in the format expected by the library. However, I couldn't find a way to create a rule in XSLT to ignore the xsi:schemaLocation that is causing the error.
The other option is create a new Transformer in Java. I was looking at Transformer.setOutputProperty, but I couldn't make a working configuration that ignores this error in crossref node.
Do you guys know how can I correctly parse the contents of crossref node in that local context?
Thanks in advance!

Remove all the characters after space in the end-tag of an xml in Java

I need to generate an xml from a Json object and I am able to do that successfully. However some of the keys in that json object look like this,
{
"UNIX":"/BIN/BASH",
"STATUS operation='remove'":"EXPIRED",
"USERS operation='remove'":"[MATT]",
"DATE operation='ADD'":"20-MAY-17",
"FIRST_NAME":"ABC",
}
So, when I am converting this Json to an xml, I am getting the xml as this,
<?xml version="1.0" encoding="UTF-8"?>
<user userid="abcid">
<UNIX>/BIN/BASH</UNIX>
<STATUS operation='remove'>EXPIRED</STATUS operation='remove'>
<USERS operation='remove'>[ILMT0004]</USERS operation='remove'>
<DATE operation='ADD'>20-APR-17</DATE operation='ADD'>
<FIRST_NAME>MATT</FIRST_NAME>
</user>
As you can see, the key in the json is getting generated as the start and the end tags in the xml, I want that operation='remove' string only in the start tag.I don't need it in the end tag of the xml. The end tag should simply be like </DATE>.
How I can get rid of any characters that are present after a space in the end tags using java?
Looks like your json is not accurate/valid (I believe it should be key value pairs, even the tree can be deeper, and the key will always be without space) to check its validity you can use any online website e.g. https://jsonformatter.org/
Your Json elements need be properly defined e.g. "FIRST_NAME":"ABC has key without space.
reference on how to convert JSON to XML - Converting JSON to XML in Java

java: Adding recursively to an xml

I need a help. how can i add content recursively to an xml file. i have a program which processes a file and send 'line information's. these line informations needs to be written to an XML file, like shown below. what i do now is I read each line info and then send it a fn which writes XML. I want to know if there is any way to Buffer the Document object and then keep keeping appending to that Document object when each new line comes.
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
- <Rev_1.28>
- <OP type="SAM">
<SRC_LN_FROM>612612</SRC_LN_FROM>
<SRC_LN_TO>703703</SRC_LN_TO>
<NO_LINES>92</NO_LINES>
</OP>
- <OP type="MOV">
<SRC_LN_FROM>6122</SRC_LN_FROM>
<SRC_LN_TO>7033</SRC_LN_TO>
<NO_LINES>9</NO_LINES>
</OP>
</Rev_1.28>
You can use DOM parser to create use org.w3c.dom.Document object as shown here.
The data is stored in primary memory, so this approach is acceptable if the data to be written is relativley small.

soap java: read and change nodes in xml files

I have a number of pre-generated, static xml files containing soap requests. I can read them, send the request, and get back and answer from the server. I would like to get some advice on how to create a dynamic process:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getProject xmlns="http://myserver/">
<atr1>string</atr1>
<atr2>string</atr2>
</getProject>
</soap:Body>
</soap:Envelope>
So, I want to be able to read these xml files, change the values of the nodes , etc. to real values gathered from user input at run-time. What would be the best way to go: read the xml file line by line and use a regex to replace value, or maybe make a temp copy of the xml file, use sax to replace the node value, then send the new xml, or completely discard the pre-generated xml files and instead create them on-the-fly, or how? Any suggestions would be appreciated.
Using regexes would be fragile, because the formatting of the XML could change in ways you're not expecting, and still be well-formed and valid XML, but not fit your regexes. In general it's not recommended to use regexes to parse XML.
Using SAX to read in the XML file (why make a temp copy?), copy all nodes to the output, modifying certain ones to put in the user-supplied values. That sounds like a good, workable solution.
Create the XML from scratch: that does sound simpler, if you know their structure in advance, and it's not too big. One way to do this would be to use an XSLT stylesheet, and pass in the user-supplied values as parameters.
You could use castor and create objects from the xml, and xml from the objects.
private void changeTagData(List<String> tagNameList, SOAPBody body) {
for(String tagName : tagNameList){
NodeList nodeList = body.getElementsByTagName(tagName);
int length = nodeList.getLength();
Node node;
for (int i = 0; i < length; i++) {
node = (Node) nodeList.item(i);
node.setTextContent("change tag data");
}
}
}
XStream can also be used in this process i am also doing some what same thing. If you like you can try XStream also.

Parse file containing XML Fragments in Java

I inherited an "XML" license file containing no root element, but rather two XML fragments (<XmlCreated> and <Product>) so when I try to parse the file, I (expectantly) get an error about a document that is not-well-formed.
I need to get both the XmlCreated and Product tags.
Sample XML file:
<?xml version="1.0"?>
<XmlCreated>May 11 2009</XmlCreated>
<!-- License Key file Attributes -->
<Product image ="LicenseKeyFile">
<!-- MyCompany -->
<Manufacturer ID="7f">
<SerialNumber>21072832521007</SerialNumber>
<ChassisId>72060034465DE1C3</ChassisId>
<RtspMaxUsers>500</RtspMaxUsers>
<MaxChannels>8</MaxChannels>
</Manufacturer>
</Product>
Here is the current code that I use to attempt to load the XML. It does not work, but I've used it before as a starting point for well-formed XML.
public static void main(String[] args) {
try {
File file = new File("C:\\path\\LicenseFile.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(file);
} catch (Exception e) {
e.printStackTrace();
}
}
At the db.parse(file) line, I get the following Exception:
[Fatal Error] LicenseFile.xml:6:2: The markup in the document following the root element must be well-formed.
org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
at com.mycompany.licensesigning.LicenseSigner.main(LicenseSigner.java:20)
How would I go about parsing this frustrating file?
If you know this document is always going to be non-well formed... make it so. Add a new dummy <root> tag after the <?xml...>and </root> after the last of the data.
You're going to need to create two separate Document objects by breaking the file up into smaller pieces and parsing those pieces individually (or alternatively reconstructing them into a larger document by adding a tag which encloses both of them).
If you can rely on the structure of the file it should be easy to read the file into a string and then search for substrings like <Product and </Product> and then use those markers to create a string you can pass into a document builder.
How about implementing a simple wrapper around InputStream that wraps the input from the file with a root-level tag, and using that as the input to DocumentBuilder.parse()?
If the expected input is small enough to load into memory, read into a string, wrap it with a dummy start/end tag and then use:
DocumentBuilder.parse(new InputSource(new StringReader(string)))
I'd probably create a SequenceInputStream where you sandwich the real stream with two ByteArrayInputStreams that return some dummy root start tag, and end tag.
Then i'd use use the parse method that takes a stream rather than a file name.
I agree with Jim Garrison to some extent, use an InputStream or StreamReader and wrap the input in the required tags, its a simple and easy method. Main problem i can forsee is you'll have to have some checks for valid and invalid formatting (if you want to be able to use the method for both valid and invalid data), if the formatting is invalid (because of root level tags missing) wrap the input with the tags, if its valid then don't wrap the input. If the input is invalid for some other reason, you can also alter the input to correct the formatting issues.
Also, its probably better to store the ipnut in a collection of strings (of some sort) rather than a string itself, this will mean that you wont have as much of a limit to your input size. Make each string one line from the file. You should end up with a logical and easy to follow structure which mwill make it easier to allow for corrections of other formatting issues in the future.
Hardest part about that is figuring out what has caused the invalid formatting. In your case just check for root level tags, if the tags exist and are formatted correctly, dont wrap, If not, wrap.

Categories