Solved

XPath query string problem

Posted on 2004-08-03
9
310 Views
Last Modified: 2006-11-17
I am parsing a Delphi DFM form file that has been converted to XML and
I want to retrieve all nodes that have a TabOrder or ObjectProperty.PropertyType.Name
element but not a HelpContext element, but only if they are not a TCSObject element.

This doesn't work:
//*[(@type="object") and (not (TCSObject)) and (not(HelpContext)) and ((TabOrder) or (ObjectProperty.PropertyType.Name))]


Using MSXML4 this doesn't work either, it returns an Unknown Method "-->local-name()<--" error
//*[(@type="object") and (not (local-name()="TCSObject")) and (not(HelpContext)) and ((TabOrder) or (ObjectProperty.PropertyType.Name))]


Here is a snippet of the XML. In this sample, I only want to return
these nodes:

  <TPanel name="FHeaderPanel" type="object">
  <TLabel name="FDepartmentLabel" type="object">
  <TLabel name="FAccountLabel" type="object">
  <TCSComboBox name="FDepartmentCombo" type="object">
  <TCSMaskEdit name="FAccountIDEdit" type="object">

<?xml version="1.0"?>
<TIssueEditForm name="IssueEditForm" type="object">
  <Left type="smallint">311</Left>
  <Top type="smallint">221</Top>
  <Width type="smallint">569</Width>
  <Height type="smallint">493</Height>
  <Caption type="string">Issue</Caption>
  <Color type="identifier">clBtnFace</Color>
  <Font.Charset type="identifier">DEFAULT_CHARSET</Font.Charset>
  <Font.Color type="identifier">clWindowText</Font.Color>
  <Font.Height type="shortint">-11</Font.Height>
  <Font.Name type="string">MS Sans Serif</Font.Name>
  <Font.Style type="set">[]</Font.Style>
  <Menu type="identifier">FMainMenu</Menu>
  <OldCreateOrder type="boolean">False</OldCreateOrder>
  <OnClose type="identifier">FormClose</OnClose>
  <OnCreate type="identifier">FormCreate</OnCreate>
  <OnShow type="identifier">FormShow</OnShow>
  <PixelsPerInch type="shortint">96</PixelsPerInch>
  <TextHeight type="shortint">13</TextHeight>
  <TPanel name="FHeaderPanel" type="object">
    <Left type="shortint">0</Left>
    <Top type="shortint">0</Top>
    <Width type="smallint">561</Width>
    <Height type="smallint">237</Height>
    <Align type="identifier">alTop</Align>
    <BevelOuter type="identifier">bvNone</BevelOuter>
    <TabOrder type="shortint">0</TabOrder>
    <TLabel name="FDepartmentLabel" type="object">
      <Left type="shortint">4</Left>
      <Top type="shortint">8</Top>
      <Width type="shortint">58</Width>
      <Height type="shortint">13</Height>
      <Caption type="string">Department:</Caption>
    </TLabel>
    <TLabel name="FAccountLabel" type="object">
      <Left type="shortint">4</Left>
      <Top type="shortint">113</Top>
      <Width type="shortint">43</Width>
      <Height type="shortint">13</Height>
      <Caption type="string">Account:</Caption>
    </TLabel>
    <TCSLabel name="FProductLabel" type="object">
      <Left type="shortint">4</Left>
      <Top type="shortint">29</Top>
      <Width type="shortint">40</Width>
      <Height type="shortint">13</Height>
      <HelpContext type="smallint">9236</HelpContext>
      <Caption type="string">Product:</Caption>
      <ObjectProperty.PropertyType.Name type="string">Unknown
</ObjectProperty.PropertyType.Name>
      <ObjectProperty.PropertyType.DataType.DataType type="shortint">0
</ObjectProperty.PropertyType.DataType.DataType>
      <ObjectProperty.PropertyType.DispatchID type="shortint">0
</ObjectProperty.PropertyType.DispatchID>
    </TCSLabel>
    <TCSComboBox name="FDepartmentCombo" type="object">
      <Left type="shortint">63</Left>
      <Top type="shortint">4</Top>
      <Width type="smallint">205</Width>
      <Height type="shortint">21</Height>
      <Content type="identifier">cbcDepartments</Content>
      <ObjectProperty.ObjectControl type="identifier">FDepartmentObject
</ObjectProperty.ObjectControl>
      <ObjectProperty.PropertyType.Name type="string">Surrogate
</ObjectProperty.PropertyType.Name>
      <ObjectProperty.PropertyType.DataType.DataType type="shortint">8
</ObjectProperty.PropertyType.DataType.DataType>
      <ObjectProperty.PropertyType.DispatchID type="shortint">1
</ObjectProperty.PropertyType.DispatchID>
      <ObjectProperty.PropertyType.AutoUpdate type="boolean">False
</ObjectProperty.PropertyType.AutoUpdate>
      <AllowBlank type="boolean">False</AllowBlank>
      <ReadOnly type="boolean">False</ReadOnly>
      <Activate type="boolean">True</Activate>
      <BorderColor type="identifier">clBtnShadow</BorderColor>
      <Flat type="boolean">True</Flat>
      <ShowBorder type="boolean">True</ShowBorder>
      <Style type="identifier">csDropDownList</Style>
      <ItemHeight type="shortint">13</ItemHeight>
      <TabOrder type="shortint">0</TabOrder>
      <OnChange type="identifier">DepartmentChange</OnChange>
      <ControlRights type="identifier">crInherited</ControlRights>
    </TCSComboBox>
    <TCSMaskEdit name="FProductIDEdit" type="object">
      <Left type="shortint">63</Left>
      <Top type="shortint">25</Top>
      <Width type="smallint">184</Width>
      <Height type="shortint">21</Height>
      <HelpContext type="smallint">9236</HelpContext>
      <ReadOnly type="boolean">False</ReadOnly>
      <TabOrder type="shortint">1</TabOrder>
      <OnChange type="identifier">IDChange</OnChange>
      <OnExit type="identifier">IDExit</OnExit>
      <ObjectProperty.ObjectControl type="identifier">FProductObject
</ObjectProperty.ObjectControl>
      <ObjectProperty.PropertyType.Name type="string">ID
</ObjectProperty.PropertyType.Name>
      <ObjectProperty.PropertyType.DataType.DataType type="shortint">8
</ObjectProperty.PropertyType.DataType.DataType>
      <ObjectProperty.PropertyType.DispatchID type="shortint">2
</ObjectProperty.PropertyType.DispatchID>
      <ObjectProperty.PropertyType.AutoUpdate type="boolean">False
</ObjectProperty.PropertyType.AutoUpdate>
      <Activate type="boolean">True</Activate>
      <BorderColor type="identifier">clBtnShadow</BorderColor>
      <Flat type="boolean">True</Flat>
      <ShowBorder type="boolean">True</ShowBorder>
      <ControlRights type="identifier">crInherited</ControlRights>
    </TCSMaskEdit>
    <TCSMaskEdit name="FAccountIDEdit" type="object">
      <Left type="shortint">63</Left>
      <Top type="shortint">109</Top>
      <Width type="smallint">184</Width>
      <Height type="shortint">21</Height>
      <ReadOnly type="boolean">False</ReadOnly>
      <TabOrder type="shortint">6</TabOrder>
      <OnChange type="identifier">IDChange</OnChange>
      <OnExit type="identifier">IDExit</OnExit>
      <ObjectProperty.ObjectControl type="identifier">FAccountObject
</ObjectProperty.ObjectControl>
      <ObjectProperty.PropertyType.Name type="string">ID
</ObjectProperty.PropertyType.Name>
      <ObjectProperty.PropertyType.DataType.DataType type="shortint">8
</ObjectProperty.PropertyType.DataType.DataType>
      <ObjectProperty.PropertyType.DispatchID type="shortint">2
</ObjectProperty.PropertyType.DispatchID>
      <ObjectProperty.PropertyType.AutoUpdate type="boolean">False
</ObjectProperty.PropertyType.AutoUpdate>
      <Activate type="boolean">True</Activate>
      <BorderColor type="identifier">clBtnShadow</BorderColor>
      <Flat type="boolean">True</Flat>
      <ShowBorder type="boolean">True</ShowBorder>
      <ControlRights type="identifier">crInherited</ControlRights>
    </TCSMaskEdit>
  </TPanel>
  <TPanel name="FMainPanel" type="object">
    <Left type="shortint">0</Left>
    <Top type="smallint">237</Top>
    <Width type="smallint">561</Width>
    <Height type="smallint">210</Height>
    <HelpContext type="longint">11182081</HelpContext>
    <Align type="identifier">alClient</Align>
    <BevelOuter type="identifier">bvNone</BevelOuter>
    <TabOrder type="shortint">1</TabOrder>
  </TPanel>
  <TCSObject name="FLocationObject" type="object">
    <ObjectType.Name type="string">ILocation</ObjectType.Name>
    <ObjectType.GUID.GUID type="string">{73923621-A2F1-11D1-A0ED-
0140339316E9}</ObjectType.GUID.GUID>
    <Binding type="identifier">bindLate</Binding>
    <ObjectProperty.PropertyType.Name type="string">Unknown
</ObjectProperty.PropertyType.Name>
    <ObjectProperty.PropertyType.DataType.DataType type="shortint">0
</ObjectProperty.PropertyType.DataType.DataType>
    <ObjectProperty.PropertyType.DispatchID type="shortint">0
</ObjectProperty.PropertyType.DispatchID>
    <ObjectProperty.PropertyType.AutoUpdate type="boolean">False
</ObjectProperty.PropertyType.AutoUpdate>
    <Persist type="boolean">True</Persist>
    <ProtectControls type="boolean">False</ProtectControls>
    <OnAssign type="identifier">LocationObjectAssign</OnAssign>
    <OnRelease type="identifier">LocationObjectRelease</OnRelease>
    <Left type="smallint">517</Left>
    <Top type="smallint">165</Top>
  </TCSObject>
  <TCSObject name="FProductObject" type="object">
    <ObjectType.Name type="string">IProduct</ObjectType.Name>
    <ObjectType.GUID.GUID type="string">{73923301-A2F1-11D1-A0ED-
0140339316E9}</ObjectType.GUID.GUID>
    <Binding type="identifier">bindLate</Binding>
    <ObjectProperty.PropertyType.Name type="string">Unknown
</ObjectProperty.PropertyType.Name>
    <ObjectProperty.PropertyType.DataType.DataType type="shortint">0
</ObjectProperty.PropertyType.DataType.DataType>
    <ObjectProperty.PropertyType.DispatchID type="shortint">0
</ObjectProperty.PropertyType.DispatchID>
    <ObjectProperty.PropertyType.AutoUpdate type="boolean">False
</ObjectProperty.PropertyType.AutoUpdate>
    <Persist type="boolean">True</Persist>
    <ProtectControls type="boolean">False</ProtectControls>
    <OnAssign type="identifier">ProductObjectAssign</OnAssign>
    <OnRelease type="identifier">ProductObjectRelease</OnRelease>
    <Left type="smallint">489</Left>
    <Top type="smallint">165</Top>
  </TCSObject>
</TIssueEditForm>
0
Comment
Question by:EddieShipman
  • 4
  • 3
  • 2
9 Comments
 
LVL 15

Expert Comment

by:dualsoul
ID: 11706371
hm...this one should be what you describe:


//*[not(self::TCSObject)][not(child::HelpContext)][@type='object'][child::TabOrder or child::ObjectProperty.PropertyType.Name]

, but it returns:

<TPanel name="FHeaderPanel" type="object"/>
<TCSComboBox name="FDepartmentCombo" type="object"/>
<TCSMaskEdit name="FAccountIDEdit" type="object"/>


, it seems right for me (as i able to check) . And the result you posted - is wrong, or may be xml sample, you posted, is not what do you mean. Please check carefully all stuff you posted and if above XPath is not what you want post again valid result with explanation for every node - why it should be returned.
0
 
LVL 26

Expert Comment

by:rdcpro
ID: 11706986
I agree with Dualsoul.  I tried a couple things this morning, and this:

    <TLabel name="FDepartmentLabel" type="object">
      <Left type="shortint">4</Left>
      <Top type="shortint">8</Top>
      <Width type="shortint">58</Width>
      <Height type="shortint">13</Height>
      <Caption type="string">Department:</Caption>
    </TLabel>
    <TLabel name="FAccountLabel" type="object">
      <Left type="shortint">4</Left>
      <Top type="shortint">113</Top>
      <Width type="shortint">43</Width>
      <Height type="shortint">13</Height>
      <Caption type="string">Account:</Caption>
    </TLabel>

should not be in the results.  They have neither a TabOrder nor an ObjectProperty.PropertyType.Name child.

This was the XPath I used:

//*[not(self::TCSObject or child::HelpContext)][child::TabOrder | child::ObjectProperty.PropertyType.Name]

Regards,
Mike Sharp
0
 
LVL 26

Author Comment

by:EddieShipman
ID: 11707469
Yes, I made a mistake. Some labels do have a HelpContext so I'm going to have to go with a Width property instead of TabOrder.
0
 
LVL 15

Expert Comment

by:dualsoul
ID: 11709351
you wanna XPath with Width instead of TabPropery?
try this:

//*[not(self::TCSObject or child::HelpContext)][child::Width | child::ObjectProperty.PropertyType.Name]

or you mean something else?
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 26

Author Comment

by:EddieShipman
ID: 11777409
Well, this isn't returning exactly the results I'm looking for.
It returns some nodes that have a Width but no HelpContext but
it also returns children of those nodes and some of those children
have a HelpContext.

The XML I posted above is not the complete, just a sample of one showing what
I wanted returned.

Is there any way to just return all nodes that have a Width and no HelpContext
regradless of parentage?
0
 
LVL 26

Accepted Solution

by:
rdcpro earned 500 total points
ID: 11778383
This part of the XPath filters to nodes that are not TCSObject nodes, and do not have HelpContext children.

//*[not(self::TCSObject or child::HelpContext)]

This part *further* filters those nodes to include only those with Width or ObjectProperty.PropertyType.Name children.  I don't see it returning any node with a HelpContext child.  Do you mean you don't want a HelpContext descendant?

//*[not(self::TCSObject or descendant::HelpContext)][child::Width | child::ObjectProperty.PropertyType.Name]

returns:

  <TLabel name="FDepartmentLabel" type="object">
  <TLabel name="FAccountLabel" type="object">
  <TCSComboBox name="FDepartmentCombo" type="object">
  <TCSMaskEdit name="FAccountIDEdit" type="object">

but does not include:
  <TPanel name="FHeaderPanel" type="object">

but TPanel contains children, at least one of which has a HelpContext child.

Regards,
Mike Sharp
0
 
LVL 26

Author Comment

by:EddieShipman
ID: 11778706
That worked. Now to be able to get the name attribute from the returned node...
0
 
LVL 26

Expert Comment

by:rdcpro
ID: 11778867
Well, this would:

<xsl:value-of select="@name"/> assuming the context was one of the nodes in the XPath (ie: in a for-each or apply-templates).  If you simply want all the name attributes, and you want to iterate over them, you could do this:

<xsl:for-each select="//*[not(self::TCSObject or descendant::HelpContext)][child::Width | child::ObjectProperty.PropertyType.Name]">
<xsl:value-of select="@name"/>
</xsl:for-each>

Or even:

<xsl:for-each select="//*[not(self::TCSObject or descendant::HelpContext)][child::Width | child::ObjectProperty.PropertyType.Name]/@name">
<xsl:value-of select="."/>
</xsl:for-each>

Regards,
Mike Sharp
0
 
LVL 26

Author Comment

by:EddieShipman
ID: 11779212
I am parsing them and loading them into a listbox in a Delphi program.
Got it, anyway.

Thanks.
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

The Problem How to write an Xquery that works like a SQL outer join, providing placeholders for absent data on the outer side?  I give a bit more background at the end. The situation expressed as relational data Let’s work through this.  I’ve …
The Client Need Led Us to RSS I recently had an investment company ask me how they might notify their constituents about their newsworthy publications.  Probably you would think "Facebook" or "Twitter" but this is an interesting client.  Their cons…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now