Advanced XPath query - xpath

I have an XML file that looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<PrivateSchool>
<Teacher id="teacher1">
<Name>
teacher1Name
</Name>
</Teacher>
<Teacher id="teacher2">
<Name>
teacher2Name
</Name>
</Teacher>
<Student id="student1">
<Name>
student1Name
</Name>
</Student>
<Student id="student2">
<Name>
student2Name
</Name>
</Student>
<Lesson student="student1" teacher="teacher1" />
<Lesson student="student2" teacher="teacher2" />
<Lesson student="student3" teacher="teacher3" />
<Lesson student="student1" teacher="teacher2" />
<Lesson student="student3" teacher="teacher3" />
<Lesson student="student1" teacher="teacher1" />
<Lesson student="student2" teacher="teacher4" />
<Lesson student="student1" teacher="teacher1" />
</PrivateSchool>
There's also a DTD associated with this XML, but I assume it's not much relevant to my question. Let's assume all needed teachers and students are well defined.
What is the XPath query that returns the teachers' NAMES, that have at least one student that took more than 10 lessons with them?
I was looking at many XPath sites/examples. Nothing seemed advanced enough for this kind of question.

Doing a complex join in a single XPath may be possible, but you're banging your head against a brick wall. XQuery or XSLT are much more suited to this kind of thing. Here it is in XQuery:
declare variable $doc as doc('data.xml');
declare function local:numLessons($teacher, $student) {
return count($doc//Lesson[#teacher = $teacher and #student = $student])
};
$doc//Teacher[some $s in //Lesson/#student satisfies local:numLessons(#id, $s) gt 10]/Name
Having done that, if you are really determined you can reduce it to XPath 2.0:
doc('data.xml')//Teacher[
for $t in . return
some $s in //Lesson/#student satisfies
count(//Lesson[#teacher = $t and #student = $s]) gt 10] /Name
Not tested.

This is an XPath 2.0 solution:
(/PrivateSchool
/Lesson)
[index-of(
/PrivateSchool
/Lesson
/concat(#student, '|', #teacher),
concat(#student, '|', #teacher)
)[10]
]/(for $teacher in #teacher
return /PrivateSchool
/Teacher[#id = $teacher]
/Name)

Use this XPath 2.0 expression:
for $limit in 2,
$t in /*/Teacher,
$id in $t/#id,
$s in /*/Student/#id,
$numLessons in
count(/*/Lesson[#teacher eq $id
and #student eq $s])
return
if($numLessons gt $limit)
then
(string-join(($t/Name, $s, xs:string($numLessons)), ' '),
'
'
)
else ()
here I have set $limit to 2, so that when this XPath expression is evaluated against the provided XML document:
<PrivateSchool>
<Teacher id="teacher1">
<Name>teacher1Name</Name>
</Teacher>
<Teacher id="teacher2">
<Name>teacher2Name</Name>
</Teacher>
<Student id="student1">
<Name>student1Name</Name>
</Student>
<Student id="student2">
<Name>student2Name</Name>
</Student>
<Lesson student="student1" teacher="teacher1" />
<Lesson student="student2" teacher="teacher2" />
<Lesson student="student3" teacher="teacher3" />
<Lesson student="student1" teacher="teacher2" />
<Lesson student="student3" teacher="teacher3" />
<Lesson student="student1" teacher="teacher1" />
<Lesson student="student2" teacher="teacher4" />
<Lesson student="student1" teacher="teacher1" />
</PrivateSchool>
it produces the correct result:
teacher1Name student1 3
In your real expression you'll have $limit set to 10 and will only return the teachers' names:
for $limit in 10,
$t in /*/Teacher,
$id in $t/#id,
$s in /*/Student/#id,
$numLessons in
count(/*/Lesson[#teacher eq $id
and #student eq $s])
return
if($numLessons gt $limit)
then ($t/Name, '
')
else ()

The solution posted by Michael Kay for xpath 2.0 is correct, but aproximate. An exact solution for the xml posted at the question would be (without absolute paths):
//Teacher[
for $t in . return
some $s in //Student satisfies
count(//Lesson[#teacher = $t/#id and #student = $s/#id]) gt 1
]/Name
(I used "gt 1" instead of "gt 10" in order to get some result)

Related

BI Publisher Ring Chart Thickness

I am relatively new to BI Publisher and I have to date only worked with line and bar charts.
I am working on a report that uses Ring Charts, and the default thickness of the chart is too much. I want it to look like a hoola hoop and not a doughnut, as below. But I dont know what node to change in the XML, can someone advise?
Chart Currently looks like this:
I would like it to look like this:
Any help is greatly appreciated.
Thanks
Chart Code
<Graph seriesEffect="SE_NONE" graphType="RING">
<LegendArea visible="false" />
<SeriesItems>
<Series id="0" color="#447A27" />
<Series id="1" color="#96b27f" />
<Series id="2" color="#c4c5c7" />
<Series id="3" color="#EA4848" />
<Series id="4" color="#C41C24" />
</SeriesItems>
<SliceLabel visible="false">
<ViewFormat decimalDigit="0" decimalDigitUsed="true" />
</SliceLabel>
<LocalGridData colCount="1" rowCount="{count(.//DATASET[condition='Test'])}">
<RowLabels>
<xsl:for-each select=".//DATASET[condition='Test']" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<Label>
<xsl:value-of select="QUALITY_LEVEL" />
</Label>
</xsl:for-each>
</RowLabels>
<DataValues>
<xsl:for-each select=".//DATASET[condition='Test']" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<RowData>
<Cell>
<xsl:value-of select="COUNT" />
</Cell>
</RowData>
</xsl:for-each>
</DataValues>
</LocalGridData>
<RingTotalLabel>
<GraphFont size="50" fontColor="#c4c5c7" />
</RingTotalLabel>
</Graph>

Formatting legend in Anychart included with Application Express

I am trying to format the legend within Application Express Anychart Flash chart. Here is the relevant XML section:
<legend enabled="true" position="Right" align="Near" elements_layout="Vertical">
<title enabled="true">
<text>Legend</text>
<font family="Tahoma" size="10" color="0x000000" />
</title>
<icon>
<marker enabled="true" />
</icon>
<font family="Tahoma" size="10" color="0x000000" />
</legend>
I am simply trying to add two line items, Sales and Tickets, to describe the lines in my chart with a correctly colored line icons but instead I get two generic entries - Value and Value. Can anyone help me sort out the proper code for this XML?
When I change it to the following:
<legend enabled="true" position="Right" align="Near" elements_layout="Vertical" ignore_auto_item="True">
<title enabled="true">
<text>Legend</text>
<font family="Tahoma" size="10" color="0x000000" />
</title>
<items>
<item>
<text>This is a test</text>
</icon></item>
<item><text>Item 2</text>
</item>
</items>
<icon>
<marker enabled="true" />
</icon>
<font family="Tahoma" size="10" color="0x000000" />
</legend>
This gives me the two series I want but no icon.
Please forgive my ignorance here. I still am not getting the simple legend I want. I am using two series queries, Total_Sales and Total_Tickets:
SELECT NULL Link,
trunc(tix.timestamp) AS label,
sum(tixp.Price) AS value
FROM LS_tickets tix LEFT OUTER JOIN
LS_ticket_prices tixP
ON tixp.series_prefix = tix.ticket_series
WHERE tix.event_id = :P145_event_id
and tix.event_id = tixp.event_id
and tix.voided_flag != 'Y'
GROUP BY trunc(tix.timestamp)
ORDER BY trunc(tix.timestamp) ASC
And
SELECT NULL Link,
trunc(tix.timestamp) AS label,
sum( tixp.quantity ) AS value
FROM LS_tickets tix LEFT OUTER JOIN
LS_ticket_prices tixP
ON tixp.series_prefix = tix.ticket_series
WHERE tix.event_id = :P145_event_id
and tix.event_id = tixp.event_id
and tix.voided_flag != 'Y'
GROUP BY trunc(tix.timestamp)
ORDER BY 1
But I am getting an empty legend whenever i try and add ICON information specific for each label as follows:
<legend enabled="true" position="Right" align="Near" elements_layout="Vertical" ignore_auto_item="True">
<title enabled="true">
<text>Legend</text>
<font family="Tahoma" size="10" color="0x000000" />
</title>
<icon><marker enabled="true" /></icon>
<items>
<item source="Series" series="Total_Sales">
<text>{%Icon} Sales</text>
</item>
<item source="Series" series="Total_Tickets"><text>{%Icon} Tickets</text>
</item>
</items>
<font family="Tahoma" size="10" color="0x000000" />
</legend>
It depends on what data structure you are using. You can specify what data should be shown in legend using these xml settings.
Each automatic item have attributes source which can be "Points" or "Series" and series, that specifies the series name:
http://www.anychart.com/products/anychart/docs/users-guide/index.html?legend-text-formatting.html#automatic-items
In case of custom line items you can add your own items with any information:
http://www.anychart.com/products/anychart/docs/users-guide/index.html?legend-text-formatting.html#custom-items
Here is a list of all keywords that you can use to format the items values:
http://www.anychart.com/products/anychart/docs/users-guide/index.html?legend-text-formatting.html#keywords
it looks like the issue occurs while apex working with the series, all of them are created with the name set to "VALUE. Here is a solution for the similar problem:
https://community.oracle.com/message/12637203#12637203

Adding a custom button to the advanced find robbon

I've got my customizations.xml importing ok, but when I open the Advanced Find Dialog, it tell me "Ribbon XML Validation Error":
I can't seem to get any more info than that. Below is my customizations.xml text, I've tried to simplify it as much as possible.
<ImportExportXml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Entities></Entities>
<Roles></Roles>
<Workflows></Workflows>
<FieldSecurityProfiles></FieldSecurityProfiles>
<Templates />
<RibbonDiffXml>
<CustomActions>
<CustomAction Id="DEW.Mscrm.AdvancedFind.Groups.Debug.UploadFetchXml"
Location="Mscrm.AdvancedFind.Groups.Debug._children" >
<CommandUIDefinition>
<Button Id="DEW.Mscrm.AdvancedFind.Groups.Debug.UploadFetchXmlButton" />
</CommandUIDefinition>
</CustomAction>
</CustomActions>
<Templates>
<RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
</Templates>
<CommandDefinitions>
</CommandDefinitions>
<RuleDefinitions>
<TabDisplayRules />
<DisplayRules />
<EnableRules />
</RuleDefinitions>
<LocLabels />
</RibbonDiffXml>
<EntityMaps />
<EntityRelationships />
<OrganizationSettings />
<optionsets />
<Languages>
<Language>1033</Language>
</Languages>
</ImportExportXml>
For others looking to find the solution, or at least something to take note of if you're having a similar problem.
My problem was that the id for the different elements were the same. You must have unique id's even among different elements. And "Mscrm.AdvancedFind.Groups.Debug._children" should have been "Mscrm.AdvancedFind.Groups.Debug.Controls._children"

Need to figure out xpath to get sibling node

I have to return a certain node that is a sibling to a node that I am using to select a certain parent of both nodes...
suppose...
<?xml version="1.0" encoding="utf-16"?>
<dataTemplateSpecification id="id1" name="name1">
<templates xmlns="">
<template>
<elements>
<element id="element0" name="PatientId" display="Patient ID" dataType="String" visable="true" readOnly="false" value="32">
<mapping path="//Template/TemplateData/ACOData/PATIENT_ID" />
<validation>
<rules>
<rule id="r0" test="#element0.value == ''">
<fail>
<html>
<b>Patient ID is null, value must be present</b>
</html>
</fail>
</rule>
</rules>
</validation>
</element>
<element id="element4" name="Active" display="ACTIVE" dataType="String" visable="true" readOnly="true" value="A">
<mapping path="//Template/TemplateData/ACOData/ACTIVE" />
<!--//Templates/Patient/sources/source/empi"/>-->
<validation>
<rules>
<rule id="r1" test="#element1.value == ''">
<fail>
<html>
<b>EMPI ID is null, value must be present</b>
</html>
</fail>
</rule>
</rules>
</validation>
</element>
<element id="element2" name="PopulationPatientID" display="Population Patient ID" dataType="String" visable="true" readOnly="true" enc="223" value="198">
<mapping path="//Template/TemplateData/ACOData/POPULATION_PATIENT_ID" />
<!--Patient/compositeID[./idType='populationPatientID']/id-->
<validation>
<rules>
<rule id="r1" test="#element1.value == ''">
<fail>
<html>
<b>EMPI ID is null, value must be present</b>
</html>
</fail>
</rule>
</rules>
</validation>
</element>
<element id="element1" name="EncounterId" display="Encounter ID" dataType="String" visable="true" readOnly="false" value="223">
<mapping path="//Template/TemplateData/ACOData/FOCUSED_READMISSIONS_ID" />
<validation>
<rules>
<rule id="r0" test="#element0.value == ''">
<fail>
<html>
<b>Patient ID is null, value must be present</b>
</html>
</fail>
</rule>
</rules>
</validation>
</element>
The Xpath I have right now currently only gets the right template. But I need the right element...
//dataTemplateSpecification/templates/template[./elements/element[#name="PopulationPatientID" and #value="198" and #enc="223"]]
I need to xpath to the node that has an attribute named "Active" Is that even possible? I was thinking I might need to drill backwords in the [] section... you know [./../../] where I would be selecting by a finer granularity before then... //dataTemplateSpecification/templates/template/elements/element[./../../] ect.. Does that make sense or am I completely rambling here? Any help would be appreciated. Thanks.
The reason you are getting the template instead of the element with your XPath search is because you are searching for template.
//dataTemplateSpecification/templates/template[./elements/element[#name="PopulationPatientID" and #value="198" and #enc="223"]]
If you want the element instead, you need to specify it before the predicate part of the XPath statement (the predicate being the part in [ ] or brackets).
Also, if you are looking for the element with the name attribute that has a value of "Active", you can specify it as part of your XPath statement.
Either one of the following statements will get the element with that has a name of "Active":
/dataTemplateSpecification/templates/template/elements/element[#name = 'Active']
//element[#name = 'Active']
Use:
/*/*/*/*/element
[#name="PopulationPatientID" and #value="198" and #enc="223"]
/preceding-sibling::element[1]
or even simpler:
/*/*/*/*/element[#name='Active']
#royerboat and #Dimitre Novatchev...
both of you guys had the right idea and it inspired me to get the Xpath that I needed...
//dataTemplateSpecification/templates/template[./elements/element[#name="PopulationPatientID" and #value="198" and #enc="223"]]//element[#name = 'Active']
That xpath is precisely what I need. Dimitre, I tried both of your sugestions and they came close, but no cigar. Thanks for the help guys.

How do I find a list of subclasses for a propel model with concrete inheritance

I'm building a mini-cms for my local charity (yes, I know I could use a floss project, but they want custom coded)
My propel schema currently looks as such:-
<?xml version="1.0" encoding="UTF-8"?>
<database name="sja" defaultIdMethod="native">
<table name="section">
<column name="id" type="INTEGER" primaryKey="true" required="true" autoIncrement="true" />
<column name="title" type="VARCHAR" required="true" />
<column name="slug" type="VARCHAR" required="true" />
</table>
<table name="page">
<column name="id" type="INTEGER" primaryKey="true" required="true" autoIncrement="true" />
<column name="title" type="VARCHAR" required="true" />
<column name="section_id" type="INTEGER" required="true" />
<foreign-key foreignTable="section">
<reference local="section_id" foreign="id" />
</foreign-key>
</table>
<table name="static_page">
<behavior name="concrete_inheritance">
<parameter name="extends" value="page" />
</behavior>
<column name="content" type="LONGVARCHAR" required="true" />
</table>
<table name="home_page">
<behavior name="concrete_inheritance">
<parameter name="extends" value="page" />
</behavior>
<column name="standfirst_title" type="VARCHAR" />
<column name="standfirst_image" type="VARCHAR" />
<column name="standfirst_content" type="VARCHAR" />
</table>
</database>
I want to be able to get a list that would include "home_page" and "static_page" - without having to create this manually whenever I add a new page type.
Is there an easy way to get a list like this, or do I have to write some magic stuff with Reflection Classes, etc?
After a poke in the right direction from #propel on freenode - I've come up with this for a base concept - haven't tested it yet though
function getSubClasses()
{
$map = $this->getDatabaseMap();
$children = array();
foreach ($map->getRelations() AS $relation)
{
$behaviours = $relation->getRightTable()->getBehaviours();
if (issset($behaviours['concrete_inheritance']['extends']) AND $behaviours['concrete_inheritance']['extends'] == $this->getDatabaseMap()->getClassName())
{
$children[] = $relation->getRightTable()->getClassName();
}
}
return $children;
}

Resources