use of org.dom4j.XPath in project pentaho-kettle by pentaho.
the class GetXMLData method applyXPath.
@SuppressWarnings("unchecked")
private boolean applyXPath() {
try {
XPath xpath = data.document.createXPath(data.PathValue);
if (meta.isNamespaceAware()) {
xpath = data.document.createXPath(addNSPrefix(data.PathValue, data.PathValue));
xpath.setNamespaceURIs(data.NAMESPACE);
}
// get nodes list
data.an = xpath.selectNodes(data.document);
data.nodesize = data.an.size();
data.nodenr = 0;
} catch (Exception e) {
logError(BaseMessages.getString(PKG, "GetXMLData.Log.ErrorApplyXPath", e.getMessage()));
return false;
}
return true;
}
use of org.dom4j.XPath in project openolat by klemens.
the class ImsCPFileResource method validateImsManifest.
private static boolean validateImsManifest(Document doc) {
try {
// do not throw exception already here, as it might be only a generic zip file
if (doc == null)
return false;
// get all organization elements. need to set namespace
Element rootElement = doc.getRootElement();
String nsuri = rootElement.getNamespace().getURI();
Map<String, String> nsuris = new HashMap<>(1);
nsuris.put("ns", nsuri);
// Check for organiztaion element. Must provide at least one... title gets ectracted from either
// the (optional) <title> element or the mandatory identifier attribute.
// This makes sure, at least a root node gets created in CPManifestTreeModel.
XPath meta = rootElement.createXPath("//ns:organization");
meta.setNamespaceURIs(nsuris);
// TODO: accept several organizations?
Element orgaEl = (Element) meta.selectSingleNode(rootElement);
if (orgaEl == null) {
return false;
}
// Check for at least one <item> element referencing a <resource>, which will serve as an entry point.
// This is mandatory, as we need an entry point as the user has the option of setting
// CPDisplayController to not display a menu at all, in which case the first <item>/<resource>
// element pair gets displayed.
XPath resourcesXPath = rootElement.createXPath("//ns:resources");
resourcesXPath.setNamespaceURIs(nsuris);
Element elResources = (Element) resourcesXPath.selectSingleNode(rootElement);
if (elResources == null) {
// no <resources> element.
return false;
}
XPath itemsXPath = rootElement.createXPath("//ns:item");
itemsXPath.setNamespaceURIs(nsuris);
List items = itemsXPath.selectNodes(rootElement);
if (items.size() == 0) {
// no <item> element.
return false;
}
for (Iterator iter = items.iterator(); iter.hasNext(); ) {
Element item = (Element) iter.next();
String identifierref = item.attributeValue("identifierref");
if (identifierref == null)
continue;
XPath resourceXPath = rootElement.createXPath("//ns:resource[@identifier='" + identifierref + "']");
resourceXPath.setNamespaceURIs(nsuris);
Element elResource = (Element) resourceXPath.selectSingleNode(elResources);
if (elResource == null) {
return false;
}
if (elResource.attribute("scormtype") != null) {
return false;
}
if (elResource.attribute("scormType") != null) {
return false;
}
if (elResource.attribute("SCORMTYPE") != null) {
return false;
}
if (elResource.attributeValue("href") != null) {
// success.
return true;
}
}
} catch (Exception e) {
log.warn("", e);
}
return false;
}
use of org.dom4j.XPath in project openolat by klemens.
the class ScormCPFileResource method validateImsManifest.
public static boolean validateImsManifest(Document doc) {
try {
// do not throw exception already here, as it might be only a generic zip file
if (doc == null)
return false;
String adluri = null;
String seqencingUri = null;
String simpleSeqencingUri = null;
// get all organization elements. need to set namespace
Element rootElement = doc.getRootElement();
String nsuri = rootElement.getNamespace().getURI();
// look for the adl cp namespace that differs a scorm package from a normal cp package
Namespace nsADL = rootElement.getNamespaceForPrefix("adlcp");
if (nsADL != null)
adluri = nsADL.getURI();
Namespace nsADLSeq = rootElement.getNamespaceForPrefix("adlseq");
if (nsADLSeq != null)
seqencingUri = nsADLSeq.getURI();
Namespace nsADLSS = rootElement.getNamespaceForPrefix("imsss");
if (nsADLSS != null)
simpleSeqencingUri = nsADLSS.getURI();
// we can only support scorm 1.2 so far.
if (adluri != null && !((adluri.indexOf("adlcp_rootv1p2") != -1) || (adluri.indexOf("adlcp_rootv1p3") != -1))) {
// we dont have have scorm 1.2 or 1.3 namespace so it can't be a scorm package
return false;
}
Map<String, Object> nsuris = new HashMap<>(5);
nsuris.put("ns", nsuri);
// we might have a scorm 2004 which we do not yet support
if (seqencingUri != null)
nsuris.put("adlseq", seqencingUri);
if (simpleSeqencingUri != null)
nsuris.put("imsss", simpleSeqencingUri);
// Check for organization element. Must provide at least one... title gets extracted from either
// the (optional) <title> element or the mandatory identifier attribute.
// This makes sure, at least a root node gets created in CPManifestTreeModel.
XPath meta = rootElement.createXPath("//ns:organization");
meta.setNamespaceURIs(nsuris);
// TODO: accept several organizations?
Element orgaEl = (Element) meta.selectSingleNode(rootElement);
if (orgaEl == null) {
return false;
}
// Check for at least one <item> element referencing a <resource> of adlcp:scormtype="sco" or "asset",
// which will serve as an entry point.
XPath resourcesXPath = rootElement.createXPath("//ns:resources");
resourcesXPath.setNamespaceURIs(nsuris);
Element elResources = (Element) resourcesXPath.selectSingleNode(rootElement);
if (elResources == null) {
return false;
}
XPath itemsXPath = rootElement.createXPath("//ns:item");
itemsXPath.setNamespaceURIs(nsuris);
List items = itemsXPath.selectNodes(rootElement);
if (items.size() == 0) {
// no <item> element.
return false;
}
// check for scorm 2004 simple sequencing stuff which we do not yet support
if (seqencingUri != null) {
XPath seqencingXPath = rootElement.createXPath("//ns:imsss");
List sequences = seqencingXPath.selectNodes(rootElement);
if (sequences.size() > 0) {
// seqencing elements found -> scorm 2004
return false;
}
}
Set<String> set = new HashSet<String>();
for (Iterator iter = items.iterator(); iter.hasNext(); ) {
Element item = (Element) iter.next();
String identifier = item.attributeValue("identifier");
// check if identifiers are unique, reject if not so
if (!set.add(identifier)) {
// TODO:create special error message for non unique ids
return false;
}
}
for (Iterator iter = items.iterator(); iter.hasNext(); ) {
Element item = (Element) iter.next();
String identifierref = item.attributeValue("identifierref");
if (identifierref == null)
continue;
XPath resourceXPath = rootElement.createXPath("//ns:resource[@identifier='" + identifierref + "']");
resourceXPath.setNamespaceURIs(nsuris);
Element elResource = (Element) resourceXPath.selectSingleNode(elResources);
if (elResource == null) {
return false;
}
// check for scorm attribute
Attribute scormAttr = elResource.attribute("scormtype");
// some packages have attribute written like "scormType"
Attribute scormAttrUpper = elResource.attribute("scormType");
if (scormAttr == null && scormAttrUpper == null) {
return false;
}
String attr = "";
if (scormAttr != null)
attr = scormAttr.getStringValue();
if (scormAttrUpper != null)
attr = scormAttrUpper.getStringValue();
if (attr == null) {
return false;
}
if (elResource.attributeValue("href") != null && (attr.equalsIgnoreCase("sco") || attr.equalsIgnoreCase("asset"))) {
// success.
return true;
}
}
return false;
} catch (Exception e) {
log.warn("Not a valid SCORM package", e);
return false;
}
}
use of org.dom4j.XPath in project openolat by klemens.
the class ItemContext method shuffle.
/**
* Method shuffle. shuffle clones the current item (since the whole qti tree
* is readonly) and shuffles it
*
* @param item
* @return Element
*/
private Element shuffle(Element item) {
// get the render_choice
XPath choice = DocumentHelper.createXPath(".//render_choice[@shuffle=\"Yes\"]");
Element tel_rendchoice = (Element) choice.selectSingleNode(item);
// if shuffle is disable, just return the item
if (tel_rendchoice == null)
return item;
// else: we have to shuffle
// assume: all response_label have same parent: either render_choice or a
// flow_label
Element shuffleItem = item.createCopy();
// clone the whole item
Element el_rendchoice = (Element) choice.selectSingleNode(shuffleItem);
// <!ELEMENT render_choice ((material | material_ref | response_label |
// flow_label)* ,response_na?)>
// <!ATTLIST response_label rshuffle (Yes | No ) 'Yes' .....
List el_labels = el_rendchoice.selectNodes(".//response_label[@rshuffle=\"Yes\"]");
int shusize = el_labels.size();
// set up a list of children with their parents and the position of the
// child (in case several children have the same parent
List<Element> respList = new ArrayList<>(shusize);
List<Element> parentList = new ArrayList<>(shusize);
int[] posList = new int[shusize];
int j = 0;
for (Iterator responses = el_labels.iterator(); responses.hasNext(); ) {
Element response = (Element) responses.next();
Element parent = response.getParent();
int pos = parent.indexOf(response);
posList[j++] = pos;
// need to use clones so they are not
respList.add((Element) response.clone());
// attached anymore
parentList.add(parent);
}
Collections.shuffle(respList);
// put the children back to the parents
for (int i = 0; i < parentList.size(); i++) {
Element parent = parentList.get(i);
int pos = posList[i];
Element child = respList.get(i);
parent.elements().set(pos, child);
}
return shuffleItem;
}
use of org.dom4j.XPath in project openolat by klemens.
the class ResultsBuilder method getResDoc.
/**
* Method getResDoc.
*
* @param ai The assessment instance
* @param locale The users locale
* @param identity
* @return Document The XML document
*/
public Document getResDoc(AssessmentInstance ai, Locale locale, Identity identity) {
AssessmentContext ac = ai.getAssessmentContext();
DocumentFactory df = DocumentFactory.getInstance();
Document res_doc = df.createDocument();
Element root = df.createElement("qti_result_report");
res_doc.setRootElement(root);
Element result = root.addElement("result");
Element extension_result = result.addElement("extension_result");
String baseUrl = ai.getResolver().getStaticsBaseURI() + "/";
// extension_result.
for (int i = 0; i < ac.getSectionContextCount(); i++) {
SectionContext sectionCtx = ac.getSectionContext(i);
for (int j = 0; j < sectionCtx.getItemContextCount(); j++) {
// OO-148
// on some occasions this did throw an IllegalAddException
// because el_item had already a parent.
// make a clone for adding to extension_result
Element el_item = (Element) sectionCtx.getItemContext(j).getEl_item().clone();
recurseMattextForMediaURLFiltering(baseUrl, el_item);
extension_result.add(el_item);
}
}
// add ims cp id for any media references
addStaticsPath(extension_result, ai);
// add assessment_result
// Add User information
Element context = result.addElement("context");
User user = identity.getUser();
String name = user.getProperty(UserConstants.FIRSTNAME, locale) + " " + user.getProperty(UserConstants.LASTNAME, locale);
String instId = user.getProperty(UserConstants.INSTITUTIONALUSERIDENTIFIER, locale);
String instName = user.getProperty(UserConstants.INSTITUTIONALNAME, locale);
if (instId == null)
instId = "N/A";
context.addElement("name").addText(name);
String institution;
if (instName == null) {
institution = "N/A";
} else {
institution = instName;
}
// Add institutional identifier (e.g. Matrikelnummer)
Element generic_identifier = context.addElement("generic_identifier");
generic_identifier.addElement("type_label").addText(institution);
generic_identifier.addElement("identifier_string").addText(instId);
// Add start and stop date formatted as datetime
Element beginDate = context.addElement("date");
beginDate.addElement("type_label").addText("Start");
beginDate.addElement("datetime").addText(Formatter.formatDatetime(new Date(ac.getTimeOfStart())));
Element stopDate = context.addElement("date");
stopDate.addElement("type_label").addText("Stop");
stopDate.addElement("datetime").addText(Formatter.formatDatetime(new Date(ac.getTimeOfStop())));
Element ares = result.addElement("assessment_result");
ares.addAttribute("ident_ref", ac.getIdent());
if (ac.getTitle() != null) {
ares.addAttribute("asi_title", ac.getTitle());
}
// process assessment score
Element a_score = ares.addElement("outcomes").addElement("score");
a_score.addAttribute("varname", "SCORE");
String strVal = StringHelper.formatFloat(ac.getScore(), 2);
a_score.addElement("score_value").addText(strVal);
strVal = ac.getMaxScore() == -1.0f ? "N/A" : StringHelper.formatFloat(ac.getMaxScore(), 2);
a_score.addElement("score_max").addText(strVal);
strVal = ac.getCutvalue() == -1.0f ? "N/A" : StringHelper.formatFloat(ac.getCutvalue(), 2);
a_score.addElement("score_cut").addText(strVal);
addElementText(ares, "duration", QTIHelper.getISODuration(ac.getDuration()));
addElementText(ares, "num_sections", "" + ac.getSectionContextCount());
addElementText(ares, "num_sections_presented", "0");
addElementText(ares, "num_items", "" + ac.getItemContextCount());
addElementText(ares, "num_items_presented", "" + ac.getItemsPresentedCount());
addElementText(ares, "num_items_attempted", "" + ac.getItemsAttemptedCount());
// add section_result
int secnt = ac.getSectionContextCount();
for (int i = 0; i < secnt; i++) {
SectionContext secc = ac.getSectionContext(i);
Element secres = ares.addElement("section_result");
secres.addAttribute("ident_ref", secc.getIdent());
if (secc.getTitle() != null) {
secres.addAttribute("asi_title", secc.getTitle());
}
addElementText(secres, "duration", QTIHelper.getISODuration(secc.getDuration()));
addElementText(secres, "num_items", "" + secc.getItemContextCount());
addElementText(secres, "num_items_presented", "" + secc.getItemsPresentedCount());
addElementText(secres, "num_items_attempted", "" + secc.getItemsAttemptedCount());
// process section score
Element sec_score = secres.addElement("outcomes").addElement("score");
sec_score.addAttribute("varname", "SCORE");
strVal = secc.getScore() == -1.0f ? "N/A" : "" + StringHelper.formatFloat(secc.getScore(), 2);
sec_score.addElement("score_value").addText(strVal);
strVal = secc.getMaxScore() == -1.0f ? "N/A" : "" + StringHelper.formatFloat(secc.getMaxScore(), 2);
sec_score.addElement("score_max").addText(strVal);
strVal = secc.getCutValue() == -1 ? "N/A" : "" + secc.getCutValue();
sec_score.addElement("score_cut").addText(strVal);
// iterate over all items in this section context
List<ItemContext> itemsc = secc.getSectionItemContexts();
for (Iterator<ItemContext> it_it = itemsc.iterator(); it_it.hasNext(); ) {
ItemContext itemc = it_it.next();
Element itres = secres.addElement("item_result");
itres.addAttribute("ident_ref", itemc.getIdent());
itres.addAttribute("asi_title", itemc.getEl_item().attributeValue("title"));
Element it_duration = itres.addElement("duration");
it_duration.addText(QTIHelper.getISODuration(itemc.getTimeSpent()));
// process item score
DecimalVariable scoreVar = (DecimalVariable) (itemc.getVariables().getSCOREVariable());
Element it_score = itres.addElement("outcomes").addElement("score");
it_score.addAttribute("varname", "SCORE");
it_score.addElement("score_value").addText(StringHelper.formatFloat(scoreVar.getTruncatedValue(), 2));
strVal = scoreVar.hasMinValue() ? "" + scoreVar.getMinValue() : "0.0";
it_score.addElement("score_min").addText(strVal);
strVal = scoreVar.hasMaxValue() ? "" + scoreVar.getMaxValue() : "N/A";
it_score.addElement("score_max").addText(strVal);
strVal = scoreVar.hasCutValue() ? "" + scoreVar.getCutValue() : "N/A";
it_score.addElement("score_cut").addText(strVal);
Element el_item = itemc.getEl_item();
Map<String, Element> res_responsehash = new HashMap<>(3);
// iterate over all responses of this item
List resps = el_item.selectNodes(".//response_lid|.//response_xy|.//response_str|.//response_num|.//response_grp");
for (Iterator it_resp = resps.iterator(); it_resp.hasNext(); ) {
Element resp = (Element) it_resp.next();
String ident = resp.attributeValue("ident");
String rcardinality = resp.attributeValue("rcardinality");
String rtiming = resp.attributeValue("rtiming");
// add new response
Element res_response = itres.addElement("response");
res_response.addAttribute("ident_ref", ident);
// enable lookup of
res_responsehash.put(ident, res_response);
// @identref of <response>
// (needed with <varequal>
// elements
// add new response_form
// <response_lid ident="MR01" rcardinality="Multiple" rtiming="No">
Element res_responseform = res_response.addElement("response_form");
res_responseform.addAttribute("cardinality", rcardinality);
res_responseform.addAttribute("timing", rtiming);
String respName = resp.getName();
String type = respName.substring(respName.indexOf("_") + 1);
res_responseform.addAttribute("response_type", type);
// add user answer
ItemInput itemInp = itemc.getItemInput();
Translator trans = Util.createPackageTranslator(QTIModule.class, locale);
if (itemInp == null) {
// user did not answer this question at all
res_response.addElement("response_value").addText(trans.translate("ResBuilder.NoAnswer"));
} else {
List<String> userAnswer = itemInp.getAsList(ident);
if (userAnswer == null) {
// user did not answer this question at
// all
res_response.addElement("response_value").addText(trans.translate("ResBuilder.NoAnswer"));
} else {
// simply click send)
for (Iterator<String> it_ans = userAnswer.iterator(); it_ans.hasNext(); ) {
res_response.addElement("response_value").addText(it_ans.next());
}
}
}
}
/*
* The simple element correct_response can only list correct elements,
* that is, no "or" or "and" elements may be in the conditionvar.
* Pragmatic solution: if condition has ors or ands, then put whole
* conditionvar into <extension_response> (proprietary), and for easier
* cases (just "varequal" "not" elements) use correct_response.
*/
// keys: respIdents, values: HashSet
Map<String, Set<String>> corr_answers = new HashMap<>();
// of correct answers for this
// respIdent
List respconds = el_item.selectNodes(".//respcondition");
for (Iterator it_respc = respconds.iterator(); it_respc.hasNext(); ) {
Element el_respc = (Element) it_respc.next();
// check for add/set in setvar elements (check for single instance
// only -> spec allows for multiple instances)
Element el_setvar = (Element) el_respc.selectSingleNode(".//setvar");
if (el_setvar == null)
continue;
if (el_setvar.attributeValue("action").equals("Add") || el_setvar.attributeValue("action").equals("Set")) {
// This resrocessing gives points -> assume correct answer
float numPoints = 0;
try {
numPoints = Float.parseFloat(el_setvar.getTextTrim());
} catch (NumberFormatException nfe) {
//
}
if (numPoints <= 0)
continue;
Element conditionvar = (Element) el_respc.selectSingleNode(".//conditionvar");
// there is an evaluation defined (a "resprocessing" element exists)
// if (xpath(count(.//varequal) + count(.//not) = count(.//*)) is
// true, then there are only "not" and "varequal" elements
XPath xCanHandle = DocumentHelper.createXPath("count(.//varequal) + count(.//not) = count(.//*)");
boolean canHandle = xCanHandle.matches(conditionvar);
if (!canHandle) {
// maybe we have <condvar> <and> <...>, try again
Element el_and = (Element) conditionvar.selectSingleNode("and");
if (el_and != null) {
canHandle = xCanHandle.matches(el_and);
if (canHandle) {
// simultate the el_and to be the conditionvar
conditionvar = el_and;
}
} else {
// and finally, maybe we have an <or> element ..
Element el_or = (Element) conditionvar.selectSingleNode("or");
if (el_or != null) {
canHandle = xCanHandle.matches(el_or);
if (canHandle) {
// simultate the el_and to be the conditionvar
conditionvar = el_or;
}
}
}
}
if (!canHandle) {
// qti res 1.2.1 can't handle it
Element condcopy = conditionvar.createCopy();
itres.addElement("extension_item_result").add(condcopy);
} else {
/*
* easy case: get all varequal directly under the conditionvar
* element and assume the "not" elements do not contain "not"
* elements again... <!ELEMENT response (qti_comment? ,
* response_form? , num_attempts? , response_value* ,
* extension_response?)> <!ELEMENT response_form
* (correct_response* , extension_responseform?)> <!ELEMENT
* correct_response (#PCDATA)>
*/
List vareqs = conditionvar.selectNodes("./varequal");
for (Iterator it_vareq = vareqs.iterator(); it_vareq.hasNext(); ) {
/*
* get the identifier of the response, so that we can attach the
* <correct_response> to the right <response> element quote: ims
* qti asi xml binding :3.6.23.1 <varequal> Element: respident
* (required). The identifier of the corresponding
* <response_lid>, <response_xy>, etc. element (this was
* assigned using its ident attribute).
*/
Element vareq = (Element) it_vareq.next();
String respIdent = vareq.attributeValue("respident");
Set<String> respIdent_corr_answers = corr_answers.get(respIdent);
if (respIdent_corr_answers == null)
respIdent_corr_answers = new HashSet<String>(3);
respIdent_corr_answers.add(vareq.getText());
corr_answers.put(respIdent, respIdent_corr_answers);
}
// for varequal
}
// else varequal
}
// add/set setvar
}
// for resprocessing
Set<String> resp_ids = corr_answers.keySet();
for (Iterator<String> idents = resp_ids.iterator(); idents.hasNext(); ) {
String respIdent = idents.next();
Set<String> respIdent_corr_answers = corr_answers.get(respIdent);
Element res_response = res_responsehash.get(respIdent);
Element res_respform = res_response.element("response_form");
for (Iterator<String> iter = respIdent_corr_answers.iterator(); iter.hasNext(); ) {
String answer = iter.next();
res_respform.addElement("correct_response").addText(answer);
}
}
}
// for response_xy
}
return res_doc;
}
Aggregations