diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java index 1eca92857a47dd723b8ad14c665bf70490d80a21..35ff41396d5b31722f74ce6d2a13cb6dd6320939 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java +++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java @@ -1371,7 +1371,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController removeAsListenerAndDispose(overviewConfigCtrl); overviewConfigCtrl = new AssessmentTestOverviewConfigurationController(ureq, getWindowControl(), toolbar, - testEntry, resolvedAssessmentTest); + testEntry, resolvedAssessmentTest, manifestBuilder); listenTo(overviewConfigCtrl); toolbar.pushController(translate("configuration.overview"), overviewConfigCtrl); } diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties index 46cde4ff5276fddf0bdad7c169dd7366d1d7322e..09a82212a965e66ed566301d1a0e55383325852f 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties @@ -31,6 +31,9 @@ delete=L\u00F6schen delete.item=$org.olat.ims.qti.editor\:delete.item delete.section=$org.olat.ims.qti.editor\:delete.section delete.testPart=Wollen Sie den Test-Part mit allen Fragen wirklich l\u00F6schen? +duration.m=m +duration.h=h +duration.s=s editor.sc.title=Single choice editor.unkown.title=Unbekanntes interaction error.assessment.item=$\:error.assessment.test @@ -241,6 +244,7 @@ table.header.attempts=L\u00F6sungsversuche table.header.comment=Kommentar erlauben table.header.feedback=Feedback table.header.identifier=Frage ID +table.header.learning.time=Zeit table.header.points=Punkte table.header.review=R\u00FCckblick erlauben table.header.skipping=\u00DCberspringen erlauben diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties index b932152ff6a7366e580aac880bc02d5b9e2fc2bd..e54e2257d8155bc5b56c8caece999a9a7aa4b6e7 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties @@ -31,6 +31,9 @@ delete=Delete delete.item=$org.olat.ims.qti.editor\:delete.item delete.section=$org.olat.ims.qti.editor\:delete.section delete.testPart=Do you really want to delete the test part along with all its questions? +duration.m=m +duration.h=h +duration.s=s editor.sc.title=Single choice editor.unkown.title=Unkown interaction error.assessment.item=$\:error.assessment.test @@ -241,6 +244,7 @@ table.header.attempts=Attempts table.header.comment=Allow comment table.header.identifier=Question ID table.header.feedback=Feedback +table.header.learning.time=Time table.header.points=Points table.header.review=Allow review table.header.skipping=Allow skipping diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/overview/AssessmentTestOverviewConfigurationController.java b/src/main/java/org/olat/ims/qti21/ui/editor/overview/AssessmentTestOverviewConfigurationController.java index 632d8126b4386dd588ff451e30aa9da96807cf07..c9db885a1879af4603cd6a9e9dec62ad1a8af75a 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/overview/AssessmentTestOverviewConfigurationController.java +++ b/src/main/java/org/olat/ims/qti21/ui/editor/overview/AssessmentTestOverviewConfigurationController.java @@ -19,9 +19,9 @@ */ package org.olat.ims.qti21.ui.editor.overview; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.DoubleAdder; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; @@ -49,6 +49,7 @@ import org.olat.core.gui.translator.Translator; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.course.assessment.AssessmentHelper; +import org.olat.ims.qti21.model.xml.ManifestBuilder; import org.olat.ims.qti21.model.xml.QtiNodesExtractor; import org.olat.ims.qti21.ui.assessment.components.QuestionTypeFlexiCellRenderer; import org.olat.ims.qti21.ui.editor.AssessmentTestComposerController; @@ -83,15 +84,17 @@ public class AssessmentTestOverviewConfigurationController extends FormBasicCont private final TooledStackedPanel toolbar; private final RepositoryEntry testEntry; + private final ManifestBuilder manifestBuilder; private final ResolvedAssessmentTest resolvedAssessmentTest; @Autowired private UserManager userManager; public AssessmentTestOverviewConfigurationController(UserRequest ureq, WindowControl wControl, TooledStackedPanel toolbar, - RepositoryEntry testEntry, ResolvedAssessmentTest resolvedAssessmentTest) { + RepositoryEntry testEntry, ResolvedAssessmentTest resolvedAssessmentTest, ManifestBuilder manifestBuilder) { super(ureq, wControl, "overview", Util.createPackageTranslator(AssessmentTestComposerController.class, ureq.getLocale())); this.testEntry = testEntry; + this.manifestBuilder = manifestBuilder; this.resolvedAssessmentTest = resolvedAssessmentTest; this.toolbar = toolbar; initForm(ureq); @@ -174,6 +177,8 @@ public class AssessmentTestOverviewConfigurationController extends FormBasicCont DefaultFlexiColumnModel scoreCol = new DefaultFlexiColumnModel(PartCols.maxScore, SelectionTarget.maxpoints.name()); scoreCol.setCellRenderer(new AssessmentSectionScoreCellRenderer(SelectionTarget.maxpoints.name())); tableColumnModel.addFlexiColumnModel(scoreCol); + // typical learning time + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(PartCols.learningTime, new DurationFlexiCellRenderer(getTranslator()))); // max attempts tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(PartCols.attempts, SelectionTarget.attempts.name(), new MaxAttemptsCellRenderer(getTranslator()))); @@ -217,74 +222,84 @@ public class AssessmentTestOverviewConfigurationController extends FormBasicCont List<ControlObjectRow> rows = new ArrayList<>(); AssessmentTest test = resolvedAssessmentTest.getTestLookup().getRootNodeHolder().getRootNode(); - rows.add(ControlObjectRow.valueOf(test)); - + ControlObjectRow testRow = ControlObjectRow.valueOf(test); + rows.add(testRow); + + AggregatedValues aggregatedValues = new AggregatedValues(); List<TestPart> parts = test.getTestParts(); if(parts.size() == 1) { List<AssessmentSection> sections = parts.get(0).getAssessmentSections(); for(AssessmentSection section:sections) { - loadModel(section, rows); + AggregatedValues values = loadModel(section, rows); + aggregatedValues.add(values); } } else { for(int i=0; i<parts.size(); i++) { - loadModel(parts.get(i), (i+1), rows); + AggregatedValues values = loadModel(parts.get(i), (i+1), rows); + aggregatedValues.add(values); } } + if(aggregatedValues.getLearningTime() != null) { + testRow.setLearningTime(aggregatedValues.getLearningTime()); + } + tableModel.setObjects(rows); tableEl.reset(true, true, true); } - private void loadModel(TestPart part, int pos, List<ControlObjectRow> rows) { + private AggregatedValues loadModel(TestPart part, int pos, List<ControlObjectRow> rows) { ControlObjectRow partRow = ControlObjectRow.valueOf(part, pos); rows.add(partRow); - boolean someMaxScore = false; - DoubleAdder atomicMaxScore = new DoubleAdder(); + AggregatedValues aggregatedValues = new AggregatedValues(); List<AssessmentSection> sections = part.getAssessmentSections(); for(AssessmentSection section:sections) { - Double maxScore = loadModel(section, rows); - if(maxScore != null) { - someMaxScore = true; - atomicMaxScore.add(maxScore.doubleValue()); - } + AggregatedValues values = loadModel(section, rows); + aggregatedValues.add(values); } - if(someMaxScore) { - partRow.setMaxScore(Double.valueOf(atomicMaxScore.sum())); + if(aggregatedValues.getMaxScore() != null) { + partRow.setMaxScore(aggregatedValues.getMaxScore()); + } + if(aggregatedValues.getLearningTime() != null) { + partRow.setLearningTime(aggregatedValues.getLearningTime()); } + return aggregatedValues; } - private Double loadModel(AssessmentSection section, List<ControlObjectRow> rows) { + private AggregatedValues loadModel(AssessmentSection section, List<ControlObjectRow> rows) { ControlObjectRow sectionRow = ControlObjectRow.valueOf(section); rows.add(sectionRow); - - boolean someMaxScore = false; - DoubleAdder atomicMaxScore = new DoubleAdder(); + + AggregatedValues aggregatedValues = new AggregatedValues(); for(SectionPart part: section.getSectionParts()) { - Double maxScore = null; + AggregatedValues values = null; if(part instanceof AssessmentItemRef) { - maxScore = loadModel((AssessmentItemRef)part, rows); + values = loadModel((AssessmentItemRef)part, rows); } else if(part instanceof AssessmentSection) { - maxScore = loadModel((AssessmentSection) part, rows); + values = loadModel((AssessmentSection) part, rows); } - if(maxScore != null) { - someMaxScore = true; - atomicMaxScore.add(maxScore.doubleValue()); + if(values != null) { + aggregatedValues.add(values); } } - if(someMaxScore) { - sectionRow.setMaxScore(Double.valueOf(atomicMaxScore.sum())); + if(aggregatedValues.getMaxScore() != null) { + sectionRow.setMaxScore(aggregatedValues.getMaxScore()); + } + if(aggregatedValues.getLearningTime() != null) { + sectionRow.setLearningTime(aggregatedValues.getLearningTime()); } - return sectionRow.getMaxScore(); + return new AggregatedValues(sectionRow.getMaxScore(), sectionRow.getLearningTime()); } - private Double loadModel(AssessmentItemRef itemRef, List<ControlObjectRow> rows) { + private AggregatedValues loadModel(AssessmentItemRef itemRef, List<ControlObjectRow> rows) { Double maxScore = null; + Long learningTime = null; ResolvedAssessmentItem resolvedAssessmentItem = resolvedAssessmentTest.getResolvedAssessmentItem(itemRef); if(resolvedAssessmentItem == null || resolvedAssessmentItem.getItemLookup() == null || resolvedAssessmentItem.getItemLookup().getRootNodeHolder() == null) { @@ -295,13 +310,13 @@ public class AssessmentTestOverviewConfigurationController extends FormBasicCont rows.add(ControlObjectRow.errorOf(itemRef)); } else { AssessmentItem assessmentItem = resolvedAssessmentItem.getItemLookup().getRootNodeHolder().getRootNode(); - ControlObjectRow row = ControlObjectRow.valueOf(itemRef, assessmentItem); + ControlObjectRow row = ControlObjectRow.valueOf(itemRef, assessmentItem, manifestBuilder); maxScore = row.getMaxScore(); + learningTime = row.getLearningTime(); rows.add(row); - } } - return maxScore; + return new AggregatedValues(maxScore, learningTime); } @Override @@ -324,6 +339,45 @@ public class AssessmentTestOverviewConfigurationController extends FormBasicCont // } + private static class AggregatedValues { + + private BigDecimal maxScore = null; + private Long learningTime = null; + + public AggregatedValues() { + // + } + + public AggregatedValues(Double maxScore, Long learningTime) { + this.maxScore = maxScore == null ? null : BigDecimal.valueOf(maxScore.doubleValue()); + this.learningTime = learningTime; + } + + public Double getMaxScore() { + return maxScore == null ? null : Double.valueOf(maxScore.doubleValue()); + } + + public Long getLearningTime() { + return learningTime; + } + + public void add(AggregatedValues values) { + if(values != null) { + if(maxScore == null) { + maxScore = values.maxScore; + } else if(values.getMaxScore() != null) { + maxScore = maxScore.add(values.maxScore); + } + + if(learningTime == null) { + learningTime = values.getLearningTime(); + } else if(values.getLearningTime() != null) { + learningTime += values.getLearningTime(); + } + } + } + } + private static class TestAndSectionCellRenderer implements FlexiCellRenderer { private final FlexiCellRenderer delegate; diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/overview/AssessmentTestOverviewDataModel.java b/src/main/java/org/olat/ims/qti21/ui/editor/overview/AssessmentTestOverviewDataModel.java index 0e95d2ebfbd25ff0593bfd732cd97abab5b4aa3a..f6b5d34c2e9a131ebbd1c8ffd8cc8d9f8505ff08 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/overview/AssessmentTestOverviewDataModel.java +++ b/src/main/java/org/olat/ims/qti21/ui/editor/overview/AssessmentTestOverviewDataModel.java @@ -49,6 +49,7 @@ public class AssessmentTestOverviewDataModel extends DefaultFlexiTableDataModel< case type: return partRow.getType(); case identifier: return partRow.getIdentifier(); case feedback: return partRow.getFeedbacks(); + case learningTime: return partRow.getLearningTime(); default: return "ERROR"; } } @@ -69,7 +70,8 @@ public class AssessmentTestOverviewDataModel extends DefaultFlexiTableDataModel< solution("table.header.solution"), type("table.header.type"), identifier("table.header.identifier"), - feedback("table.header.feedback"); + feedback("table.header.feedback"), + learningTime("table.header.learning.time"); private final String i18nKey; diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/overview/ControlObjectRow.java b/src/main/java/org/olat/ims/qti21/ui/editor/overview/ControlObjectRow.java index bdf55a05b2dc1ab19166e2197601f9c14792fec7..e9eb94fe8e4d9ac883e2dee26b48567f2cf02610 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/overview/ControlObjectRow.java +++ b/src/main/java/org/olat/ims/qti21/ui/editor/overview/ControlObjectRow.java @@ -21,8 +21,13 @@ package org.olat.ims.qti21.ui.editor.overview; import java.util.List; +import org.olat.core.util.StringHelper; import org.olat.ims.qti21.model.QTI21QuestionType; +import org.olat.ims.qti21.model.xml.ManifestBuilder; +import org.olat.ims.qti21.model.xml.ManifestMetadataBuilder; import org.olat.ims.qti21.model.xml.QtiNodesExtractor; +import org.olat.modules.qpool.manager.MetadataConverterHelper; +import org.olat.modules.qpool.model.LOMDuration; import uk.ac.ed.ph.jqtiplus.node.QtiNode; import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem; @@ -56,6 +61,8 @@ public class ControlObjectRow { private OptionAndInheritance solution; private MaxAttemptOption attemptOption; + private Long typicalLearningTime; + public ControlObjectRow(String title, ControlObject<?> part, String iconCssClass) { this.part = part; this.title = title; @@ -93,7 +100,7 @@ public class ControlObjectRow { return new ControlObjectRow("ERROR", itemRef, "o_icon_error"); } - public static ControlObjectRow valueOf(AssessmentItemRef itemRef, AssessmentItem assessmentItem) { + public static ControlObjectRow valueOf(AssessmentItemRef itemRef, AssessmentItem assessmentItem, ManifestBuilder manifestBuilder) { String itemCssClass; QTI21QuestionType type = QTI21QuestionType.getType(assessmentItem); if(type != null) { @@ -107,6 +114,16 @@ public class ControlObjectRow { boolean hasFeedbacks = !assessmentItem.getModalFeedbacks().isEmpty(); row.feedbacks = Boolean.valueOf(hasFeedbacks); configuration(row, itemRef); + + ManifestMetadataBuilder metadata = manifestBuilder.getResourceBuilderByHref(itemRef.getHref().toString()); + if(metadata != null && metadata.getLom(false) != null) { + String learningTime = metadata.getEducationalLearningTime(); + if(StringHelper.containsNonWhitespace(learningTime)) { + LOMDuration duration = MetadataConverterHelper.convertDuration(learningTime); + row.typicalLearningTime = Long.valueOf(MetadataConverterHelper.convertToSeconds(duration)); + } + } + return row; } @@ -232,6 +249,9 @@ public class ControlObjectRow { return OptionEnum.no; } + + + public String getTitle() { return title; } @@ -284,6 +304,14 @@ public class ControlObjectRow { return attemptOption; } + public Long getLearningTime() { + return typicalLearningTime; + } + + public void setLearningTime(Long learningTime) { + this.typicalLearningTime = learningTime; + } + public int getDepth() { int depth = 0; for(ControlObject<?> parent=part.getParent(); parent != null; parent = parent.getParent()) { diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/overview/DurationFlexiCellRenderer.java b/src/main/java/org/olat/ims/qti21/ui/editor/overview/DurationFlexiCellRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..1524c02317b2fdd28407590f7de811f9431c7775 --- /dev/null +++ b/src/main/java/org/olat/ims/qti21/ui/editor/overview/DurationFlexiCellRenderer.java @@ -0,0 +1,63 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.ims.qti21.ui.editor.overview; + +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponent; +import org.olat.core.gui.render.Renderer; +import org.olat.core.gui.render.StringOutput; +import org.olat.core.gui.render.URLBuilder; +import org.olat.core.gui.translator.Translator; + +/** + * + * Initial date: 25 juin 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class DurationFlexiCellRenderer implements FlexiCellRenderer { + + private final Translator translator; + + public DurationFlexiCellRenderer(Translator translator) { + this.translator = translator; + } + + @Override + public void render(Renderer renderer, StringOutput target, Object cellValue, + int row, FlexiTableComponent source, URLBuilder ubu, Translator trans) { + if(cellValue instanceof Long) { + long duration = ((Long)cellValue).longValue(); + + long h = duration / (60*60); + long hmins = h*60*60; + long m = (duration - hmins) / (60); + long s = (duration - hmins - m * 60)/1000; + + if(h > 0) { + target.append(" ").append(h).append(translator.translate("duration.h")); + } + target.append(" ").append(m).append(translator.translate("duration.m")); + if(s > 0) { + target.append(" ").append(s).append(translator.translate("duration.s")); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/modules/qpool/manager/MetadataConverterHelper.java b/src/main/java/org/olat/modules/qpool/manager/MetadataConverterHelper.java index c85f155d0f1d86f3c46d5079de2ad898cf712fa0..0e11b05df1b0a68fb6c6c3059496bf5a27e2d0ab 100644 --- a/src/main/java/org/olat/modules/qpool/manager/MetadataConverterHelper.java +++ b/src/main/java/org/olat/modules/qpool/manager/MetadataConverterHelper.java @@ -134,6 +134,16 @@ public class MetadataConverterHelper { } } + public static long convertToSeconds(LOMDuration duration) { + long time = duration.getSeconds(); + time += (duration.getMinute() * 60); + time += (duration.getHour() * (60 * 60)); + time += (duration.getDay() * (60 * 60 * 24)); + time += (duration.getMonth() * (60 * 60 * 24 * 30)); + time += (duration.getYear() * (60 * 60 * 24 * 30 * 365)); + return time; + } + private static void convertDurationT(String durationStr, LOMDuration duration) { int indexH = durationStr.indexOf('H'); if(indexH >= 0) { @@ -158,131 +168,4 @@ public class MetadataConverterHelper { String intVal = durationStr.substring(0, index); return Integer.parseInt(intVal); } - /* - protected void toLom(QuestionItemImpl item, OutputStream out) { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setValidating(false); - factory.setNamespaceAware(false); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document document = builder.newDocument(); - - Element lomEl = (Element)document.appendChild(document.createElement("lom")); - - generalToLom(item, lomEl, document); - - DOMSource domSource = new DOMSource(document); - StreamResult streamResult = new StreamResult(out); - Transformer serializer = TransformerFactory.newInstance().newTransformer(); - serializer.transform(domSource, streamResult); - } catch (Exception e) { - log.error("", e); - } - } - - protected void generalToLom(QuestionItemImpl item, Node lomEl, Document doc) { - Node generalEl = lomEl.appendChild(doc.createElement("general")); - - //identifier - - //master identifier - - //title - Node titleEl = generalEl.appendChild(doc.createElement("title")); - stringToLom(item, item.getTitle(), titleEl, doc); - //description - Node descEl = generalEl.appendChild(doc.createElement("description")); - stringToLom(item, item.getDescription(), descEl, doc); - //keywords - - //coverage - - //additional information - - //language - Element languageEl = (Element)generalEl.appendChild(doc.createElement("language")); - languageEl.setAttribute("value", item.getLanguage()); - } - - protected void taxonomyToLom(QuestionItemImpl item, Node lomEl, Document doc) { - Node generalEl = lomEl.appendChild(doc.createElement("classification")); - - } - - protected void educationalToLom(QuestionItemImpl item, Node lomEl, Document doc) { - Node generalEl = lomEl.appendChild(doc.createElement("educational")); - - } - - protected void lifecycleToLom(QuestionItemImpl item, Node lomEl, Document doc) { - Node generalEl = lomEl.appendChild(doc.createElement("lifecycle")); - - //version - //status - //urheber / contribute - - } - - protected void rightsToLom(QuestionItemImpl item, Node lomEl, Document doc) { - Node generalEl = lomEl.appendChild(doc.createElement("rights")); - - //copyright - //description - - } - - protected void stringToLom(QuestionItemImpl item, String value, Node el, Document doc) { - Element stringEl = (Element)el.appendChild(doc.createElement("string")); - stringEl.setAttribute("value", value); - stringEl.setAttribute("language", item.getLanguage()); - } - - protected void toItem(QuestionItemImpl item, InputStream in) { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setValidating(false); - factory.setNamespaceAware(false); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document document = builder.parse(new InputSource(in)); - - for(Node child=document.getDocumentElement().getFirstChild(); child != null; child=child.getNextSibling()) { - if(Node.ELEMENT_NODE != child.getNodeType()) continue; - - String name = child.getNodeName().toLowerCase(); - if("educational".equals(name)) { - - } else if("general".equals(name)) { - generalToItem(item, (Element)child); - } - } - } catch (Exception e) { - log.error("", e); - } - } - - private void generalToItem(QuestionItemImpl item, Element generalEl) { - for(Node child=generalEl.getFirstChild(); child != null; child=child.getNextSibling()) { - if(Node.ELEMENT_NODE != child.getNodeType()) continue; - - String name = child.getNodeName().toLowerCase(); - if("title".equals(name)) { - item.setTitle(getString((Element)child)); - } else if("description".equals(name)) { - item.setDescription(getString((Element)child)); - } - } - } - - private String getString(Element el) { - String val = null; - for(Node child=el.getFirstChild(); child != null; child=child.getNextSibling()) { - if(Node.ELEMENT_NODE != child.getNodeType()) continue; - - String name = child.getNodeName().toLowerCase(); - if("string".equals(name)) { - val = ((Element)child).getAttribute("value"); - } - } - return val; - }*/ }