?
Solved

XPath query string problem

Posted on 2004-08-03
9
Medium Priority
?
356 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:Eddie Shipman
  • 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:Eddie Shipman
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
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
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
 
LVL 26

Author Comment

by:Eddie Shipman
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 2000 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:Eddie Shipman
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:Eddie Shipman
ID: 11779212
I am parsing them and loading them into a listbox in a Delphi program.
Got it, anyway.

Thanks.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
The Confluence of Individual Knowledge and the Collective Intelligence At this writing (summer 2013) the term API (http://dictionary.reference.com/browse/API?s=t) has made its way into the popular lexicon of the English language.  A few years ago, …
Watch the video to know how one can repair corrupt Exchange OST file effortlessly and convert OST emails to MS Outlook PST file format by using Kernel for OST to PST converter tool. It can convert OST to MSG, MBOX, EML to access them. It can migrate…
When you have multiple client accounts to manage, it often feels like there aren’t enough hours in the day. With too many applications to juggle, you can’t focus on your clients, much less your growing to-do list. But that doesn’t have to be the cas…

589 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