my dog learned polymorphism*
The moose likes Java in General and the fly likes Recreate XML file Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Recreate XML file" Watch "Recreate XML file" New topic
Author

Recreate XML file

Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
1. I have a XML string
2. There is a DTD available for that xml document.
Now I need to insert the DTD text after the <?xml version="1.0"?>.
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
How would I add the following line to an XML document?
>
> <!DOCTYPE QueryDef SYSTEM "QueryDef.dtd">
>
Here's an example document I`d like to create:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QueryDef SYSTEM "QueryDef.dtd">
<QueryDef>
...
</QueryDef>

Thanks
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

It looks fine to me.
/Rene


Regards, Rene Larsen
Dropbox Invite
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
Rene,do you know how to insert the DTD text after the <?xml version="1.0"?>? Based your suggestion in my previous question, I need to create a DTD file to validate a xml file.
Here is the method I created. xmlString may or may not include a DTD. I want to replace it with my DTD if it has.
public void validateXMLFile(String xmlString) throws CommandException
{
Document d = null;
try {
DOMParser parser = new DOMParser ();
parser.parse (new InputSource (new StringReader (xmlString)));
d = parser.getDocument ();
} catch (Exception e) {
throw new CommandException("Error:" + e.getMessage());
}

}
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Here's a simple approach:

Here we're assuming that the original XML string doesn't have any comments containing "?>" or "<!DOCTYPE", which would confuse it (since we should ignore stuff in comments, but this method doesn't.) If that's a problem, you'll have to do something more elaborate to screen out comments.
[ July 23, 2002: Message edited by: Jim Yingst ]

"I'm not back." - Bill Harding, Twister
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

This is the way a DOM document is normaly made:

You turn the DTD validation on/off with 'dbf.setValidating(true);'
Here is a xml/DTD sample:
Test.dtd
<!ELEMENT CONFIG (CSS_SCRIPT, XSL_LIB, XML_LIB)>
<!ELEMENT CSS_SCRIPT (#PCDATA)>
<!ELEMENT XML_LIB (#PCDATA)>
<!ELEMENT XSL_LIB (#PCDATA)>
XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE CONFIG SYSTEM "Test.dtd">
<CONFIG>
<CSS_SCRIPT>C:\\unitlink\\util\\css\\unitlink.css</CSS_SCRIPT>
<XSL_LIB>C:\\unitlink\\util\\xsl</XSL_LIB>
<XML_LIB>C:\\unitlink\\util\\xml</XML_LIB>
</CONFIG>
/Rene
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Rene, I think the problem is that some of the files Amy's looking at don't have any DOCTYPE declaration in them, and so any validation that's performed will only extend to checking for well-formedness. Unless we explicitly insert a DTD declaration into the file before validation. That's what my method above is intended to address. Or am I missing something?
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

Jim, I think you have a point there.
But then I have shown how to make the the parser able to validate a XML document.
/Rene
[ July 23, 2002: Message edited by: Rene Larsen ]
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
Thanks for your help. Both of you gave me a good idea how to recreate/validate the XML document. But we don't know whether the XML file has any DOCTYPE declaration or not.
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
Rene,
Could you please tell me what 's different between your validate method and mine? What else I need to import for your method except thhe folllowing one?
import javax.xml.parsers.DocumentBuilderFactory;
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
I'm not good at Java. I don't know whether we can search the input xmlString, replace the dtd with system fwdtd.dtd if the xmlString has DTD;otherwise, insert DTD after the "?>".
Here are examples of XML and DTD (fwdtd.dtd):
<?xml version="1.0"?>
<project name="XML Generator Application">
<command name="View">
<codeBase>xmlgenerator.commands.View</codeBase>
<target name="success">/viewXMLDocument.jsp</target>
<target name="fail">/Error.jsp</target>
<requestparameter get="true" set="false" name="userFile">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="action">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="xmlDocument">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="xmlFile">java.lang.String</requestparameter>
<requestparameter get="false" set="true" name="msg">java.lang.String</requestparameter>
<requestparameter get="false" set="true" name="viewList">java.util.Vector</requestparameter>
</command>
</project>
_______________________________________________
<!ELEMENT codeBase ( #PCDATA ) >
<!ELEMENT command ( codeBase, target+, requestparameter+ ) >
<!ATTLIST command name NMTOKEN #REQUIRED >
<!ELEMENT project ( command ) >
<!ATTLIST project name CDATA #REQUIRED >
<!ELEMENT requestparameter ( #PCDATA ) >
<!ATTLIST requestparameter get NMTOKEN #REQUIRED >
<!ATTLIST requestparameter name NMTOKEN #REQUIRED >
<!ATTLIST requestparameter set NMTOKEN #REQUIRED >
<!ELEMENT target ( #PCDATA ) >
<!ATTLIST target name NMTOKEN #REQUIRED >
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
I see I should import javax.xml.parsers.* for your method.
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
Rene,
I got an error "No such file or directory" even the xmlString includes contents. Do you know what the problem is?
public void validateXMLFile(String xmlString) throws CommandException {
try {
// Step 1: create a DocumentBuilderFactory and configure it
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// Set namespaceAware to true to get a DOM Level 2 tree with nodes
// containing namesapce information. This is necessary because the
// default value from JAXP 1.0 was defined to be false.
dbf.setNamespaceAware(true);
// Set the validation mode to either: no validation, DTD
// validation, or XSD validation
dbf.setValidating(true);
// Step 2: create a DocumentBuilder that satisfies the constraints
// specified by the DocumentBuilderFactory
DocumentBuilder db = dbf.newDocumentBuilder();
// Step 3: parse the input file
Document doc = db.parse(new InputSource(xmlString));
} catch (Exception e) {
throw new CommandException("Error:" + e.getMessage());
}
}
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

Try this:

Inside your XML you should specify where your DTD is e.g.

/Rene
[ July 24, 2002: Message edited by: Rene Larsen ]
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
Cool!!! Works. Thanks Rene !
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
Ooohhh... Why did I get the message "Congratulations, this document is well-formed XML." when I tried to validate some elements not included in the DTD file such as MyCommand. Does the element's name case sensitive?
<!ELEMENT project ( command+ ) >
<!ATTLIST project name CDATA #REQUIRED >
<!ELEMENT command ( codeBase?, target*, requestparameter* ) >
<!ATTLIST command name NMTOKEN #REQUIRED >
<!ELEMENT codeBase ( #PCDATA ) >
<!ELEMENT target ( #PCDATA ) >
<!ATTLIST target name NMTOKEN #REQUIRED >
<!ELEMENT requestparameter ( #PCDATA ) >
<!ATTLIST requestparameter get ( true | false ) #REQUIRED >
<!ATTLIST requestparameter name NMTOKEN #REQUIRED >
<!ATTLIST requestparameter set ( true | false ) #REQUIRED >
<!ELEMENT sessionattribute ( #PCDATA ) >
<!ATTLIST sessionattribute get ( true | false ) #REQUIRED >
<!ATTLIST sessionattribute name NMTOKEN #REQUIRED >
<!ATTLIST sessionattribute set ( true | false ) #REQUIRED >
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

Did you put the '<!DOCTYPE...' in your xml doc?
I've just tried your XML/DTD and added a new tag 'myCommand':

and got the error:
Error: URI=null Line=1: Element "project" allows no further input; "myCommand" is not allowed

/Rene
[ July 24, 2002: Message edited by: Rene Larsen ]
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
I found that you mistyped the <mycommand/>. It should be <mycommand />, a space before "/". Here is my xml file:
<?xml version="1.0"?>
<!DOCTYPE project SYSTEM "file:///C:\Program Files\IBM\VisualAge for Java\ide\project_resources\IBM WebSphere Test Environment\hosts\default_host\art\web\fwDTD.dtd">
<project name="XML Generator Application">
<Mycommand name="View">
<codeBase>xmlgenerator.commands.View</codeBase>
<target name="success">/viewXMLDocument.jsp</target>
<target name="fail">/viewXMLDocument.jsp</target>
<requestparameter get="true" set="false" name="userFile">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="action">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="xmlDocument">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="xmlFile">java.lang.String</requestparameter>
<requestparameter get="false" set="true" name="msg">java.lang.String</requestparameter>
<requestparameter get="false" set="true" name="viewList">java.util.Vector</requestparameter>
</Mycommand>
</project>
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

Still the same:
Error: URI=null Line=1: Element "project" does not allow "Mycommand" here.

I can see then you have the DTD in a URL with some spaces e.g. 'VisualAge for Java' try to place the DTD in a directory with no spaces e.g. 'C:\dtd\fwDTD.dtd'
/Rene
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
I coped the dtd file directly under C:/Working/fwDTD.dtd. But still can't validate correct.
<?xml version="1.0"?>
<!DOCTYPE project SYSTEM "file:///C:/Working/fwDTD.dtd">
<project name="XML Generator Application">
<Mycommand name="View">
<codeBase>art.xmlgenerator.commands.View</codeBase>
<target name="success">/viewXMLDocument.jsp</target>
<target name="fail">/viewXMLDocument.jsp</target>
<requestparameter get="true" set="false" name="userFile">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="action">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="xmlDocument">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="xmlFile">java.lang.String</requestparameter>
<requestparameter get="false" set="true" name="msg">java.lang.String</requestparameter>
<requestparameter get="false" set="true" name="viewList">java.util.Vector</requestparameter>
</Mycommand>
</project>
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
A mistake for file directory in my last message. It should be :
<!DOCTYPE project SYSTEM "file:\\\C:/Working/fwDTD.dtd">
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

I double checked my code and realized that you a missing a 'ErrorHandler'.
I've made a sample of the hole parser validating with an ErrorHandler:

/Rene
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

The correct syntax is: 'file:///'
/Rene
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
Thanks! Rene. It works. Now I need to focus to solve the next problem: How to insert the following line to the xml file?
<!DOCTYPE project SYSTEM "file:///C:\Program Files\IBM\VisualAge for Java\ide\project_resources\IBM WebSphere Test Environment\hosts\default_host\art\web\fwDTD.dtd">
--------------------------
<?xml version="1.0"?>
<!DOCTYPE project SYSTEM "file:///C:\Program Files\IBM\VisualAge for Java\ide\project_resources\IBM WebSphere Test Environment\hosts\default_host\art\web\fwDTD.dtd">
<project name="XML Generator Application">
<command name="View">
<codeBase>art.xmlgenerator.commands.View</codeBase>
<target name="success">/viewXMLDocument.jsp</target>
<target name="fail">/viewXMLDocument.jsp</target>
<requestparameter get="true" set="false" name="userFile">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="action">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="xmlDocument">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="xmlFile">java.lang.String</requestparameter>
<requestparameter get="false" set="true" name="msg">java.lang.String</requestparameter>
<requestparameter get="false" set="true" name="viewList">java.util.Vector</requestparameter>
</command>
</project>
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Now I need to focus to solve the next problem: How to insert the following line to the xml file?
Well, have you tried the method I showed?
But we don't know whether the XML file has any DOCTYPE declaration or not.
That's addressed in the first two lines of my method. It looks for "<!DOCTYPE" in the string. If it's found, then the document already has a dtd declaration, and so the method simply returns the original string, unaltered.
In one of your later posts, you seem to imply that maybe an existing DTD declaration should be replaced with your new declaration. That's possible too - it would be an elaboration on the method I showed. You need to decide if this is indeed what you want to do though, since it wasn't mentioned originally. Probably you need to look at the actual files you're dealing with. For the ones that have DOCTYPE declarations already - is the declaration invalid somehow? Does it need to be replaced? Or can the document be left as is?
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

Or you could convert the 'xmlString' into a StringBuffer and then use the method 'insert()'

/Rene
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
But the XML declaration is optional, so there may be no "?>", which will cause Rene's method to insert at index 1, which may well be invalid.
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

Jim, it depend, if the XML should be a valid XML then there will always be a declaration witch ends with '?>' - BUT you are right the parser will not complain if no declaration is present.
I have changed my sample:

Rene
[ July 24, 2002: Message edited by: Rene Larsen ]
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
I tried your solution, but I got an error "The method indexOf invoked for type java.lang.StringBuffer with arguments (java.lang.String)is not defined".
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
Two more questions:
1. If input already has DOCTYPE but not the same DTD file, how we replace it? Can a XML file has more than one DOCTYPE?
2. Now I use hard code to give the DTD file such as "String DTD = "<!DOCTYPE project SYSTEM \"file:///C:\Program Files\IBM\VisualAge for Java\ide\project_resources\IBM WebSphere Test Environment\hosts\default_host\art\web\fwDTD.dtd \">";", Since this web application will be moved to different web server. I'm not sure whether the path is same. But I'm sure we can put the DTD file with jsp files under same directory. Can we use dynamic code instead of this hard code?
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
Jim,
I have tested your insert method, but it doesn't work. The input and output XMLString is same.
String DTD = "<!DOCTYPE project [<!ELEMENT project ( command+ ) > " +
"<!ATTLIST project name CDATA #REQUIRED >" +
"<!ELEMENT command ( codeBase?, target*, requestparameter* ) > " +
"<!ATTLIST command name NMTOKEN #REQUIRED >" +
"<!ELEMENT codeBase ( #PCDATA ) >" +
"<!ELEMENT target ( #PCDATA ) >" +
"<!ATTLIST target name NMTOKEN #REQUIRED >" +
"<!ELEMENT requestparameter ( #PCDATA ) >" +
"<!ATTLIST requestparameter get ( true | false ) #REQUIRED >" +
"<!ATTLIST requestparameter name NMTOKEN #REQUIRED >" +
"<!ATTLIST requestparameter set ( true | false ) #REQUIRED >" +
"<!ELEMENT sessionattribute ( #PCDATA ) >" +
"<!ATTLIST sessionattribute get ( true | false ) #REQUIRED >" +
"<!ATTLIST sessionattribute name NMTOKEN #REQUIRED >" +
"<!ATTLIST sessionattribute set ( true | false ) #REQUIRED > ]>";
insert(xmlString,DTD);
System.out.println(xmlString);

--------------------------------
<?xml version="1.0"?>
<project name="XML Generator Application">
<command name="View">
<codeBase>xmlgenerator.commands.View</codeBase>
<target name="success">/viewXMLDocument.jsp</target>
<target name="fail">/viewXMLDocument.jsp</target>
<requestparameter get="true" set="false" name="userFile">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="action">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="xmlDocument">java.lang.String</requestparameter>
<requestparameter get="true" set="false" name="xmlFile">java.lang.String</requestparameter>
<requestparameter get="false" set="true" name="msg">java.lang.String</requestparameter>
<requestparameter get="false" set="true" name="viewList">java.util.Vector</requestparameter>
</command>
</project>
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
I modified Rene's code a little, and works. But I need to consider how to replace the DOCTYPE if the xmlString has a different DTD.
StringBuffer xmlBuffer = new StringBuffer(xmlString);

if (xmlString.indexOf("<!DOCTYPE") == -1) {
String DTD = "<!DOCTYPE project [<!ELEMENT project ( command+ ) > " +
"<!ATTLIST project name CDATA #REQUIRED >" +
"<!ELEMENT command ( codeBase?, target*, requestparameter* ) > " +
"<!ATTLIST command name NMTOKEN #REQUIRED >" +
"<!ELEMENT codeBase ( #PCDATA ) >" +
"<!ELEMENT target ( #PCDATA ) >" +
"<!ATTLIST target name NMTOKEN #REQUIRED >" +
"<!ELEMENT requestparameter ( #PCDATA ) >" +
"<!ATTLIST requestparameter get ( true | false ) #REQUIRED >" +
"<!ATTLIST requestparameter name NMTOKEN #REQUIRED >" +
"<!ATTLIST requestparameter set ( true | false ) #REQUIRED >" +
"<!ELEMENT sessionattribute ( #PCDATA ) >" +
"<!ATTLIST sessionattribute get ( true | false ) #REQUIRED >" +
"<!ATTLIST sessionattribute name NMTOKEN #REQUIRED >" +
"<!ATTLIST sessionattribute set ( true | false ) #REQUIRED > ]>";
int index = xmlString.indexOf("?>");
if (index == -1) { //if no declaration is present
xmlBuffer.insert (0, DTD);}
else {
xmlBuffer.insert (index+2, DTD);
}
}
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

Do you know when the xmlString has a different DTD? Or how do you get this information?
PS. Why don't you refer to a DTD doc insted of import?
/Rene
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

If you have a XML file in e.g. 'C:\xml\test.xml' and you have a DTD in e.g. 'C:\dtd\test.dtd' then you can refer to the DTD from the XML like '../xml/test.dtd' Or you could use e.g. 'http://dtd/test.dtd'
But when you have your xml as a String the parser can't find the DTD with a relativ URL.
/Rene
[ July 25, 2002: Message edited by: Rene Larsen ]
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
I'm developing a XML Generator tool providing a easy way for developers to utilize our command servlet framework. I can embed my DTD in servlet code (see my previous message). In order to prevent the user from including any other DOCTYPE in the xmlString, my code must handle the DOCTYPE check before validation.
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

One way to be sure that the right DTD is used, is to first remove any '<!DOCTYPE..' - if any - and then apply the right DTD to the xmlString..
Rene
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
Yes, that is what I need to do. Can you help me?
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

The '<!DOCTYPE..' what do they look like? Is it the hole DTD or only a refence to one?
Rene
[ July 25, 2002: Message edited by: Rene Larsen ]
Amy Howard
Ranch Hand

Joined: Jul 11, 2002
Posts: 86
I think we need to replace the whole DOCTYPE line since we don't know what the DOCTYPE it is.
Rene Larsen
Ranch Hand

Joined: Oct 12, 2001
Posts: 1179

I've modified my sample.
Try this:

PS. You should change 'xmlBuffer' with 'xmlString' where you get an error.
I'm using JDK 1.4 witch has the methods i StringBuffer.
Rene
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
 
subject: Recreate XML file