views:

44

answers:

2

Hi, all.

I've got an xml file of several recordings that looks like this:

<audiolibrary>
    <prompt name="accountinfo">
        <prompt-segment>
            <audio src="audio/default/accountinfo.wav" 
                text="Account Information"/>
        </prompt-segment>
    </prompt>
    ...
    <prompt name="accountclosed">
        <prompt-segment>
            <audio src="audio/default/accountclosed.wav"
                text="Sorry, your account is closed."/>
        </prompt-segment>
    </prompt>
</audiolibrary>

Following an XPath tutorial, I know I can retrieve, for example, the attribute of the first prompt with the following expressions:

xPathObject.compile("/audioibrary/prompt[@name='accountinfo']/prompt-segment/audiofile/@src");
xPathObject.compile("/audioibrary/prompt[1]/prompt-segment/audiofile/@src");

Now, if I want to retrieve all of the prompts, am I understanding correctly that I should iterate through .compile() statements until I come up with a blank value?

Something like this skeletal example, here?:

int index = 1;
do
{
    xPathObject.compile("/audioibrary/prompt["+ index +"]/prompt-segment/audiofile/@src");
    (Prompt content retrieval code here)
    index++;
}
while(!src.equals(""))

Or, is there a better way to retrieve the collection?

Thanks!
IVR Avenger

+4  A: 
XPathExpression expr = xPathObject.compile("/audiolibrary/promp/prompt-segment/audio/@src")
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
    //what you are going to do.... 
}
Wrikken
And if I want to retrieve all of the attributes (name, src, and text)?
IVR Avenger
Then you query for `/audiolibrary/promp/prompt-segment/audio`, and get the attributes you like from it, or you use `/audiolibrary/promp/prompt-segment/audio/@*`
Wrikken
So, if I want all three in a single "Prompt" object, I'd make a collection (such as an arraylist) for each type, fill the collections, and then empty them into a single collection of Prompts?
IVR Avenger
Erm, I don't know your _Prompt_ object, and I'm not that well versed in Java, so I don't know exactly what you mean with 'empty them into a single collection', but suffice to say, if you go for an XPath selecting prompts, you can get either named attributes as Strings with `getAttribute`, or them all in a list of Attrs in a NamedNodeMap with `getAttributes`. I don't see why you'd make a list per type if you're just going to end up assiging them to different objects later on...
Wrikken
Sounds like you're really interested in unmarshalling XML, you may be interested in XStream, JAXB, JiBX or other similar libraries.
Jon Freedman
If you are interested in XPath based XML unmarshalling check out MOXy JAXB: http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html
Blaise Doughan
A: 

A little bit XPath, a little bit Recursion:

String basePromptExpression = "/AudioLibrary/prompt";

NodeList nodes  = (NodeList) xPathObject.evaluate(basePromptExpression, promptInputSource, XPathConstants.NODESET);

for (int nodeIndex = 0; nodeIndex < nodes.getLength(); nodeIndex++)
{
    Node singleNode = nodes.item(nodeIndex);
    String promptName = singleNode.getAttributes().getNamedItem("name").getNodeValue();
    String promptSrc = findNode(singleNode, "audiofile").getAttributes().getNamedItem("src").getNodeValue();
    String promptText = findNode(singleNode, "audiofile").getAttributes().getNamedItem("text").getNodeValue();

    System.out.println("Name: "+promptName+" Src: "+promptSrc+" Text: "+promptText);
}


private static Node findNode(Node singleNode, String nodeName)
{
    Node namedNode=null;
    NodeList nodeChildren = singleNode.getChildNodes();
    Node childNode = null;

    for (int nodeIndex =0; nodeIndex < nodeChildren.getLength(); nodeIndex++)
    {
        childNode = nodeChildren.item(nodeIndex);

        if (childNode.hasChildNodes())
        {
            childNode = findNode(childNode, nodeName);
        }

        if (childNode.getNodeName().equals(nodeName))
        {
            namedNode = childNode;
            return namedNode;
        }
    }

    return namedNode;
}
IVR Avenger