Problems using commons digester to parse subversion XML output - java

The Subversion XML formatted output is a combination of attribute and elements - particularly within the <path> element - see the sample below:
<?xml version="1.0" encoding="UTF-8"?>
<log>
<logentry
revision="29">
<author>bob</author>
<date>2013-02-14T17:21:42.848605Z</date>
<paths>
<path
action="A"
kind="dir"
copyfrom-path="/trunk"
copyfrom-rev="28">/tags/TAG-0.1</path>
</paths>
<msg>Creating tag TAG-0.1</msg>
</logentry>
</log>
I'm trying to use commons digester to parse this the log content into two different POJO's (LogEntry and Path) using the following:
ArrayList<LogEntry> logEntries = new ArrayList<LogEntry>();
digester.push(logEntries);
digester.addObjectCreate("*/logentry", LogEntry.class);
digester.addSetProperties("*/logentry");
digester.addBeanPropertySetter("*/logentry/author");
digester.addBeanPropertySetter("*/logentry/date");
digester.addBeanPropertySetter("*/logentry/msg");
digester.addSetNext("*/logentry", "add");
digester.addObjectCreate("*/logentry/paths/path", Path.class);
digester.addSetProperties("*/logentry/paths/path");
digester.addBeanPropertySetter("*/logentry/paths/path", "value");
digester.addSetNext("*/logentry/paths/path", "addPath");
(note addPath adds the path object being created onto an ArrayList<Path> within the created LogEntry object)
I can't figure out why the Path class is not being fully populated. Based upon the XML I can understand why the copyfrom-rev and copyfrom-path attributes might not be getting copied (due to the hyphen) into the corresponding copyFromRev attributes.
But I can't see any reason why the kind attribute isn't being set within the Path.
Does anyone have any ideas?

I need to use a digester.addSetProperties() call to get the copyfrom-path and copyfrom-rev attributes populated:
digester.addSetProperties("*/logentry/paths/path", "copyfrom-path", "copyfrompath");
digester.addSetProperties("*/logentry/paths/path", "copyfrom-rev", "copyfromrev");
However for some reason the kind attribute still isn't being populated.

Related

Add record="RECORD_FROM_RINGING" attribute to TwilioML XML using Java in ColdFusion

We are using ColdFusion and Java to generate the Twilio Markup / XML necessary for handling Twilio calls in our webhook.
Currently, everything works well. The output xml/twiml generated looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial callerId="+18184461999">
<Number>+18554904999</Number>
</Dial>
</Response>
We generated this markup using java classes in ColdFusion, mainly because ColdFusion can't do it natively. This is the ColdFusion/Java code we currently use to generate the above xml:
<cfscript>
TWILIO_CALLER_ID = "+18184461999";
tophn="+18554904999";
objPattern = CreateObject("java","java.util.regex.Pattern").Compile(JavaCast( "string", "^[\\d\\+\\-\\(\\) ]+$"));
objMatcher=objPattern.Matcher(JavaCast( "string", tophn ));
dialBuilder = createObject("java","com.twilio.twiml.Dial$Builder").init();
dialBuilder.callerId(TWILIO_CALLER_ID);
numberbuilder= createObject("java","com.twilio.twiml.Number$Builder").init(tophn).build();
dialBuilder = dialBuilder.number(numberbuilder);
voiceTwimlResponse = createObject("java","com.twilio.twiml.VoiceResponse$Builder").dial(dialBuilder.build()).build();
response = '<?xml version="1.0" encoding="UTF-8"?>' & voiceTwimlResponse.toXml();
</cfscript>
Everything above works perfectly for our needs.
However, now we would like to add an attribute to the "Dial" element: record="RECORD_FROM_RINGING". Below is what the XML we would like generated would look like:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial callerId="+18184461999" record="RECORD_FROM_RINGING">
<Number>+18554904999</Number>
</Dial>
</Response>
How would we use ColdFusion + java to accomplish this? We have spent hours trying to figure this out, and nothing works for us. We have looked into the Record and Record$Builder classes, but found nothing that adds this attribute the way we need it. The closest we got to was being able to add a <Record /> element before the <Dial> element, but that does not work for us.
How do we add the attribute record="RECORD_FROM_RINGING" to the <Dial> element using ColdFusion and the appropriate Java classes/objects? All we require is the attribute to be set for that element.
My guess is you are using an older version of the jar which does not support all of the <Dial> attributes. Looks like the Twilio instructions link to an older version (currently 7.0.0). The GitHub version is already up to 7.8.0. Try downloading 7.8.0 or building a newer version from the source (do not forget the dependencies).
The Dial.Builder class in 7.8.0 contains a new method named options(String key, String value) which supports arbitrary attributes. Use it to set the "record" attribute like this:
...
recordOption = createObject("java","com.twilio.twiml.Dial$Record");
dialBuilder.options("record", recordOption.RECORD_FROM_RINGING.toString());
...
** Using the Dial.Record enum, instead of a hard coded string, helps insulate the code against changes in the API.
Result:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial callerId="+18185551999" record="record-from-ringing">
<Number>+18185554999</Number>
</Dial>
</Response>

Comparing xml objects java

I have an xml bundle file which I would like to read through and compare the objects within the bundle. The start position would be the mo tag until the next mo tag.
I have done xmlunit but this compares 2 xml files. I would like to be able to compare the objects within one xml bundle file.
Don't know if this makes sense. If more info is needed, I can try explain more.
Sample of the xml file:
<mo>FIELD</mo>
<pk1>DM_READEXTRACT</pk1>
<bo>F1-FieldPhysicalBO</bo>
<boData>
<field>DM_READEXTRACT</field>
<dataType>CHAR</dataType>
<isSigned>false</isSigned>
<isWorkField>false</isWorkField>
<version>9</version>
</boData>
<entities>
<processingSequence>560</processingSequence>
<sequence>560</sequence>
</entities>
<mo>FIELD</mo>
<pk1>DM_READEXTRACT</pk1>
<bo>F1-FieldPhysicalBO</bo>
<boData>
<field>DM_READEXTRACT</field>
<dataType>CHAR</dataType>
<isSigned>false</isSigned>
<isWorkField>false</isWorkField>
<version>2</version>
</boData>
<entities>
<processingSequence>30</processingSequence>
<sequence>3</sequence>
</entities>
Maybe try to unmarshall XML to java objects and than compare?
http://www.mkyong.com/java/jaxb-hello-world-example/
XMLUnit works on Nodes as well - at least 2.x does.
By looking at your example, what you want to compare is not a proper tree but a forrest - there is no root element all others are children of.
What you can do is creating a DocumentFragment for each forrest you want to compare (on both the test and control sides) and add all roots of your forrest to it - and then tell XMLUnit to work on the DocumentFragments. You can obtain an instance of a DocumentFragment by first loading the DOM Document and then calling createDocumentFragment on it.

xml to jaxb in xml cyclic references

How to convert following XML to java using jaxb
<work>
<subwork id="sub">
<ret="it">
</subwork>
<ret id="it">
<time>9</time>
</ret>
</work>
It is a bit tough since ret tag is outside subwork tag
Frst, you need to start with valid XML. I've made assumptions in correcting the XML:
<work>
<subwork id="sub">
<ret id="it"/>
</subwork>
<ret id="it">
<time>9</time>
</ret>
</work>
Second (and there are other ways of doing this), you need to create a schema that describes this XML. Without doing it for you, I'll say that the trick is to define an element, ret, and then refer to that element within the work element and again within the subwork element.
Third, you then feed that schema file (.XSD) into a tool that generates the JAXB classes. Typically this is xcj.exe (included with the Java JDK).

Apache Digester Exception: Property ... can't be set

I have a problem with Apache Digester 3.2 I hope you can help me with:
The XML I have to parse contains the following lines (and much more):
<CountryName
code = "GFR"
name = "Germany"
IsTerritory = "False"
ProfileURL = "germany.doc"/>
The rules for the digester are given by another XML-file:
<pattern value="CountryName">
<object-create-rule classname="model.CodeNamePair"/>
<set-properties-rule/>
<set-next-rule methodname="addCountry"/>
</pattern>
This should create an Object of CodeNamePair (which contains a String 'code' and a String 'name', just like in the XML above.
The next method 'addCountry' is (hopefully) not relevant for this problem which follows now:
The digester is not able to parse this part. It throws a NoSuchMethodException with message:
"java.lang.NoSuchMethodException: Property IsTerritory can't be set"
Although I don't want to parse the IsTerritory property.
Do you know if (and how) I will be able to ignore this property?
Already now: Thank you very much (I hope my question is not written too complicated)
Try
<set-properties-rule>
<ignore attr-name="IsTerritory" />
</set-properties-rule>
instead of
<set-properties-rule/>
(Not tested)

Add xmlns="" in the xml

I am getting response XML, in that I want to add xmlns attribute in each child node which is generated.
Present output:
<createProfileResponse xmlns="http://services.profile.webservices.ecaas.com">
<createProfileReturn>STRING</createProfileReturn>
</createProfileResponse>
Required output:
<createProfileResponse xmlns="http://services.profile.webservices.ecaas.com">
<createProfileReturn xmlns="">STRING</createProfileReturn>
</createProfileResponse>
How do I do this?
NOTE: I've used JAXB to generate the XML.
The problem is that you need to have "createProfileReturn" in the blank namespace, and you explicitly put the default namespace in a non-blank namespace in the surrounding tag.
If the XML parser is fully compliant you could create a "ecaaas" global namespace and use
<ecaas:createProfileResponse>
<createProfileReturn/>
</ecaas:createProfileResponse>
HIThanks for helping out, actually this we done in coding through the saopBinding class.
But we also modified the server-config.wsdd file I really didnt understand why we need wsdd file..
This gives only the service?.
Anil

Categories

Resources