Commit 63459eee authored by R.W.Majeed's avatar R.W.Majeed

fixed export XPath evaluation

parent 27662b11
package de.sekmi.histream.export;
import java.util.Iterator;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import de.sekmi.histream.io.GroupedXMLWriter;
public class DwhNamespaceResolver implements NamespaceContext{
@Override
public String getNamespaceURI(String prefix) {
if( prefix == null ){
throw new IllegalArgumentException("prefix is null");
}else if( prefix.equals(XMLConstants.DEFAULT_NS_PREFIX) ){
return GroupedXMLWriter.NAMESPACE;
}else{
return XMLConstants.NULL_NS_URI;
}
}
@Override
public String getPrefix(String namespaceURI) {
throw new UnsupportedOperationException();
}
@Override
public Iterator<String> getPrefixes(String namespaceURI) {
throw new UnsupportedOperationException();
}
}
...@@ -10,6 +10,7 @@ import de.sekmi.histream.ObservationSupplier; ...@@ -10,6 +10,7 @@ import de.sekmi.histream.ObservationSupplier;
import de.sekmi.histream.export.config.ExportDescriptor; import de.sekmi.histream.export.config.ExportDescriptor;
import de.sekmi.histream.export.config.ExportException; import de.sekmi.histream.export.config.ExportException;
import de.sekmi.histream.io.Streams; import de.sekmi.histream.io.Streams;
import de.sekmi.histream.xml.NamespaceResolver;
public class TableExportFactory { public class TableExportFactory {
private ExportDescriptor desc; private ExportDescriptor desc;
...@@ -19,7 +20,7 @@ public class TableExportFactory { ...@@ -19,7 +20,7 @@ public class TableExportFactory {
public TableExportFactory(ExportDescriptor desc){ public TableExportFactory(ExportDescriptor desc){
this.desc = desc; this.desc = desc;
factory = XPathFactory.newInstance(); factory = XPathFactory.newInstance();
ns = new DwhNamespaceResolver(); ns = new NamespaceResolver();
} }
private XPath createXPath(){ private XPath createXPath(){
......
...@@ -3,6 +3,7 @@ package de.sekmi.histream.export; ...@@ -3,6 +3,7 @@ package de.sekmi.histream.export;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPath; import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpression;
......
...@@ -13,7 +13,9 @@ import javax.xml.transform.dom.DOMResult; ...@@ -13,7 +13,9 @@ import javax.xml.transform.dom.DOMResult;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment; import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import de.sekmi.histream.ObservationException; import de.sekmi.histream.ObservationException;
import de.sekmi.histream.ext.Patient; import de.sekmi.histream.ext.Patient;
...@@ -38,26 +40,31 @@ public abstract class VisitFragmentParser extends GroupedXMLWriter { ...@@ -38,26 +40,31 @@ public abstract class VisitFragmentParser extends GroupedXMLWriter {
setDOMWriter(doc); setDOMWriter(doc);
} }
private void fixNamespaces(DocumentFragment fragment){
//fragment.setPrefix(null);
// cannot do this
}
private void setDOMWriter(Node node) throws XMLStreamException{ private void setDOMWriter(Node node) throws XMLStreamException{
Result result = new DOMResult(node); Result result = new DOMResult(node);
writer = factory.createXMLStreamWriter(result); writer = factory.createXMLStreamWriter(result);
// XXX need this? // XXX need this?
writer.setDefaultNamespace(ObservationImpl.XML_NAMESPACE); //writer.setDefaultNamespace(ObservationImpl.XML_NAMESPACE);
writer.setPrefix(XMLConstants.DEFAULT_NS_PREFIX, ObservationImpl.XML_NAMESPACE); //writer.setPrefix(XMLConstants.DEFAULT_NS_PREFIX, ObservationImpl.XML_NAMESPACE);
writer.setPrefix("xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); //writer.setPrefix("xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
} }
private void createDocument() throws ParserConfigurationException{ private void createDocument() throws ParserConfigurationException{
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
f.setNamespaceAware(true);
f.setIgnoringComments(true); f.setIgnoringComments(true);
f.setCoalescing(true); f.setCoalescing(true);
f.setIgnoringElementContentWhitespace(true); f.setIgnoringElementContentWhitespace(true);
f.setNamespaceAware(true);
DocumentBuilder builder = f.newDocumentBuilder(); DocumentBuilder builder = f.newDocumentBuilder();
doc = builder.newDocument(); doc = builder.newDocument();
// doc.getDomConfig().setParameter("namespaces", true); doc.getDomConfig().setParameter("namespaces", true);
// doc.getDomConfig().setParameter("namespace-declarations", true); doc.getDomConfig().setParameter("namespace-declarations", true);
//return doc; //return doc;
} }
...@@ -79,6 +86,7 @@ public abstract class VisitFragmentParser extends GroupedXMLWriter { ...@@ -79,6 +86,7 @@ public abstract class VisitFragmentParser extends GroupedXMLWriter {
protected void beginPatient(Patient patient) throws ObservationException { protected void beginPatient(Patient patient) throws ObservationException {
// write patient info to patient fragment // write patient info to patient fragment
currentPatient = doc.createDocumentFragment(); currentPatient = doc.createDocumentFragment();
try { try {
setDOMWriter(currentPatient); setDOMWriter(currentPatient);
} catch (XMLStreamException e) { } catch (XMLStreamException e) {
...@@ -91,6 +99,7 @@ public abstract class VisitFragmentParser extends GroupedXMLWriter { ...@@ -91,6 +99,7 @@ public abstract class VisitFragmentParser extends GroupedXMLWriter {
protected void beginEncounter(Visit visit) throws ObservationException { protected void beginEncounter(Visit visit) throws ObservationException {
if( firstVisit == false ){ if( firstVisit == false ){
// patient fragment was parsed // patient fragment was parsed
fixNamespaces(currentPatient);
patientFragment(currentPatient.getFirstChild()); patientFragment(currentPatient.getFirstChild());
firstVisit = true; firstVisit = true;
} }
...@@ -112,6 +121,7 @@ public abstract class VisitFragmentParser extends GroupedXMLWriter { ...@@ -112,6 +121,7 @@ public abstract class VisitFragmentParser extends GroupedXMLWriter {
super.endEncounter(visit); super.endEncounter(visit);
// encounter is finished // encounter is finished
// fragment should contain exactly one node -> the visit // fragment should contain exactly one node -> the visit
fixNamespaces(currentVisit);
Node node = currentVisit.getFirstChild(); Node node = currentVisit.getFirstChild();
Objects.requireNonNull(node); Objects.requireNonNull(node);
visitFragment(currentVisit.getFirstChild()); visitFragment(currentVisit.getFirstChild());
......
...@@ -4,7 +4,6 @@ import javax.xml.bind.annotation.XmlAccessType; ...@@ -4,7 +4,6 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
@XmlRootElement(name="export") @XmlRootElement(name="export")
@XmlAccessorType(XmlAccessType.NONE) @XmlAccessorType(XmlAccessType.NONE)
......
...@@ -5,13 +5,14 @@ import javax.xml.xpath.XPathConstants; ...@@ -5,13 +5,14 @@ import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory; import javax.xml.xpath.XPathFactory;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import de.sekmi.histream.ObservationSupplier; import de.sekmi.histream.ObservationSupplier;
import de.sekmi.histream.export.DwhNamespaceResolver;
import de.sekmi.histream.export.VisitFragmentSupplier; import de.sekmi.histream.export.VisitFragmentSupplier;
import de.sekmi.histream.io.FileObservationProviderTest; import de.sekmi.histream.io.FileObservationProviderTest;
import de.sekmi.histream.xml.NamespaceResolver;
import de.sekmi.histream.xml.XMLUtils; import de.sekmi.histream.xml.XMLUtils;
public class TestVisitFragmentParser { public class TestVisitFragmentParser {
...@@ -38,12 +39,14 @@ public class TestVisitFragmentParser { ...@@ -38,12 +39,14 @@ public class TestVisitFragmentParser {
private void testXPath(Node visit) throws XPathExpressionException{ private void testXPath(Node visit) throws XPathExpressionException{
XPathFactory f = XPathFactory.newInstance(); XPathFactory f = XPathFactory.newInstance();
XPath xp = f.newXPath(); XPath xp = f.newXPath();
xp.setNamespaceContext(new DwhNamespaceResolver()); xp.setNamespaceContext(new NamespaceResolver());
// XXX namespace resolver is not working // selectors always need a prefix in XPath 1
String ret = (String)xp.evaluate("namespace-uri(./*[6])", visit, XPathConstants.STRING); String ret;
System.out.println("XPath="+ret); // ret = (String)xp.evaluate("namespace-uri(./*[6])", visit, XPathConstants.STRING);
ret = (String)xp.evaluate("count(fact)", visit, XPathConstants.STRING); // System.out.println("XPath="+ret);
System.out.println("Facts:"+ret); ret = (String)xp.evaluate("count(eav:fact)", visit, XPathConstants.STRING);
// System.out.println("Facts:"+ret);
Assert.assertEquals("12", ret);
} }
} }
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:export xmlns:ns2="http://sekmi.de/ns/histream/export-v1"> <export xmlns="http://sekmi.de/ns/histream/export-v1"
xmlns:eav="http://sekmi.de/histream/ns/eav-data">
<concepts> <concepts>
<group class="diag"> <group class="diag">
<concept wildcard-notation="ICD10:*"/> <concept wildcard-notation="ICD10:*"/>
...@@ -9,15 +10,16 @@ ...@@ -9,15 +10,16 @@
</concepts> </concepts>
<patient-table> <patient-table>
<column header="pid" xpath="@id"/> <column header="pid" xpath="@id"/>
<column header="dob" xpath="birthdate"/> <column header="dob" xpath="eav:birthdate"/>
<column header="sex" xpath="gender"/> <column header="sex" xpath="eav:gender"/>
<column header="modified" xpath="eav:source/@timestamp"/>
</patient-table> </patient-table>
<visit-table> <visit-table>
<column header="vid" xpath="@id"/> <column header="vid" xpath="@id"/>
<column header="start" xpath="start"/> <column header="start" xpath="eav:start"/>
<column header="f_start" xpath="fact[@concept='T:full']/@start"/> <column header="f_start" xpath="eav:fact[@concept='T:full']/@start"/>
<column header="f_end" xpath="fact[@concept='T:full']/@end"/> <column header="f_end" xpath="eav:fact[@concept='T:full']/@end"/>
<column header="f_loc" xpath="fact[@concept='T:full']/@location"/> <column header="f_loc" xpath="eav:fact[@concept='T:full']/@location"/>
<column header="f_val" xpath="fact[@concept='T:full']/value"/> <column header="f_val" xpath="eav:fact[@concept='T:full']/eav:value"/>
</visit-table> </visit-table>
</ns2:export> </export>
...@@ -31,8 +31,8 @@ to construct table data. ...@@ -31,8 +31,8 @@ to construct table data.
<patient-table> <patient-table>
<column header="pid" xpath="@id"/> <column header="pid" xpath="@id"/>
<column header="birthdate" xpath="birthdate"/> <column header="birthdate" xpath="eav:birthdate"/>
<column header="gender" xpath="gender"/> <column header="gender" xpath="eav:gender"/>
</patient-table> </patient-table>
<visit-table> <visit-table>
<!-- context for XPath expressions is each visit node --> <!-- context for XPath expressions is each visit node -->
...@@ -41,14 +41,14 @@ to construct table data. ...@@ -41,14 +41,14 @@ to construct table data.
<column header="visit" xpath="@id"/> <column header="visit" xpath="@id"/>
<!-- concepts for the visit table must occur only once <!-- concepts for the visit table must occur only once
per visit and may not repeat --> per visit and may not repeat -->
<column header="start" xpath="start"/> <column header="start" xpath="eav:start"/>
<!-- What is better? --> <!-- What is better? -->
<!-- (a) First column, then concepts with value --> <!-- (a) First column, then concepts with value -->
<column header="diagnostik_labort_ts" xpath="facts/fact[@class='d_lab']/@start"/> <column header="diagnostik_labort_ts" xpath="eav:fact[@class='d_lab']/@start"/>
<column header="diagnostik_labort" xpath="facts/fact[@class='d_lab']/@concept"/> <column header="diagnostik_labort" xpath="eav:fact[@class='d_lab']/@concept"/>
<!-- (b) first concepts then columns with value --> <!-- (b) first concepts then columns with value -->
<column header="diagnostik_labort_ts" xpath="facts/fact[@class='d_lab']/@start"/> <column header="diagnostik_labort_ts" xpath="eav:fact[@class='d_lab']/@start"/>
<column header="diagnostik_labort" xpath="facts/fact[@class='d_lab']/modifier[@code='OPB' or @code='PB']/@code"/> <column header="diagnostik_labort" xpath="eav:fact[@class='d_lab']/eav:modifier[@code='OPB' or @code='PB']/@code"/>
<!-- We want this: <!-- We want this:
6:NEG -> not tested 6:NEG -> not tested
6/mod=OPB -> tested non pathological 6/mod=OPB -> tested non pathological
...@@ -62,6 +62,6 @@ to construct table data. ...@@ -62,6 +62,6 @@ to construct table data.
<column header="visit" xpath="visit-ref"/> <column header="visit" xpath="visit-ref"/>
<column header="start" type="@start"/> <column header="start" type="@start"/>
<column header="code" type="@concept"/> <column header="code" type="@concept"/>
<column header="primary" xpath="modifier[@code='fuehrend']/@code"/> <column header="primary" xpath="eav:modifier[@code='fuehrend']/@code"/>
</eav-table> </eav-table>
</export> </export>
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment