By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,220 Members | 1,588 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,220 IT Pros & Developers. It's quick & easy.

ID / IDREFS problem MSXML vs. System.XML

P: n/a
Hi all.

Does id() xpath function work in System.XML? I have built dtd, schema, xdr
for a simple xml which includes attributes definded as ID and IDREFS.
Validation is occurring properly for all the types of metadata, but the id()
function applied to the IDREFS attribute allways returns nothing.

I have tried it from xslt and using the XmlNode.selectnodes or
XPathNavigator.Select
nada zilch

The same code works using MSXML 3.0 and 4.0 class COM objects. I am getting
to the point of wanting to import them into .Net ( I know it is not supposed
to work that way but the code works.) I have also researched and learned
that XPath standard came before schema standard and that the different
development teams at MS have interpreted a little differently on what goes
in.

If anyone can point me to any samples that actually work with System.XML
using ID/IDREFS and XPath:id() would be greatly appreciated.

Thanks
Bill E


Nov 12 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Microsoft News wrote:
Does id() xpath function work in System.XML? I have built dtd, schema, xdr
for a simple xml which includes attributes definded as ID and IDREFS.


It does work, but requires attribute to be defined as ID in DTD, not
schema. There is some trick to get it working with schema too though.
--
Oleg Tkachenko
XML Insider
http://www.tkachenko.com/blog

Nov 12 '05 #2

P: n/a
Thanks for answering Oleg,

(I changed Outlook Express account to me not generic MS News)

I have a valid dtd which is used in validation via XMLValidatingReader and
it does pick up mistakes
( To test it I broke it a couple of different ways and it was allways
detected. )

Still can't get XPathNavigator.Select or XmlNode.SelectNodes to work with
XPATH id() function.

I saw your stuff on deriving from validating reader, I haven't tried that
with the XSD version yet and will shortly

Thanks again
Bill E.
Nov 12 '05 #3

P: n/a
Bill Eidson wrote:
I have a valid dtd which is used in validation via XMLValidatingReader and
it does pick up mistakes
( To test it I broke it a couple of different ways and it was allways
detected. )

Still can't get XPathNavigator.Select or XmlNode.SelectNodes to work with
XPATH id() function.


Well, should work. Make sure you are building XmlDocument or
XPathDocument via XmlValidatingReader. Or show us your code.
--
Oleg Tkachenko
XML Insider
http://www.tkachenko.com/blog

Nov 12 '05 #4

P: n/a
The XML

================================================== ==========================
===============
<?xml version="1.0" standalone="no"?>
<!DOCTYPE workflow SYSTEM "http://localhost/xml/WorkflowProcess.dtd">
<!--
<workflow xmlns="http://localhost/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://localhost/xml
http://localhost/xml/WorkflowProcess.xsd">
-->
<workflow xmlns="http://localhost/xml">
<Processes>
<Process processId="WelcomeEmail" errorProcessID="timeouterror"
type="email">
<Email>
<To firstName="Bob" lastName="James" occupation="Pianist"
mailto="bj****@music.org" />
<From mailto="ad***@amazon.com" />
<EmailBody templateRef="WelcomeEmailTemplate" />
</Email>
</Process>

<Process processId="WelcomePage" type="aspxPage">
<Url href="welcome.aspx" />
</Process>

<Process processId="EmailTimeout" errorProcessID="timeouterror"
type="email">
<Email>
<To mailto="ad***@music.org" />
<From mailto="ad***@amazon.com" />
<EmailBody templateRef="ErrorEmailTemplate" />
</Email>
</Process>

<Process processId="End" type="end">
<End />
</Process>
</Processes>

<Flows>
<Flow flowID="normal" processIDs="WelcomeEmail WelcomePage End" />
<Flow flowID="timeouterror" processIDs="EmailTimeout End" />
</Flows>

<Templates>
<Template templateID="WelcomeEmailTemplate"
href="file://c:emailtemplate.xslt" />
<Template templateID="ErrorEmailTemplate"
href="file://c:emailtemplate.xslt" />
</Templates>
</workflow>
================================================== ==========================
======================

DTD

<!ELEMENT workflow (Processes, Flows, Templates)>
<!ATTLIST workflow
xmlns CDATA #IMPLIED>

<!ELEMENT Processes (Process)*>

<!ELEMENT Process ( Email | Url | Start | End )>
<!ATTLIST Process
processId ID #REQUIRED
type ( email | aspxPage | end ) #REQUIRED
errorProcessID IDREF #IMPLIED >

<!ELEMENT Start EMPTY>
<!ELEMENT End EMPTY>
<!ELEMENT Url EMPTY>
<!ATTLIST Url href CDATA #REQUIRED>

<!ELEMENT Email (To, From, EmailBody )>

<!ELEMENT To EMPTY>
<!ATTLIST To
firstName CDATA #IMPLIED
lastName CDATA #IMPLIED
occupation CDATA #IMPLIED
mailto CDATA #REQUIRED>

<!ELEMENT From EMPTY>
<!ATTLIST From
firstName CDATA #IMPLIED
lastName CDATA #IMPLIED
occupation CDATA #IMPLIED
mailto CDATA #REQUIRED>

<!ELEMENT EmailBody EMPTY>
<!ATTLIST EmailBody
templateRef IDREF #REQUIRED>

<!ELEMENT Flows (Flow)*>

<!ELEMENT Flow EMPTY>
<!ATTLIST Flow
flowID ID #REQUIRED
processIDs IDREFS #REQUIRED>

<!ELEMENT Templates (Template)*>

<!ELEMENT Template EMPTY>
<!ATTLIST Template
templateID ID #REQUIRED
href CDATA #REQUIRED>

================================================== ========================

C# Code Version

try
{
System.Diagnostics.Debug.WriteLine( "Schema Collection Add..." );
XmlSchemaCollection sc = new XmlSchemaCollection();
sc.ValidationEventHandler += new
ValidationEventHandler(HandleValidationEvents);
// sc.Add( "http://localhost/xml", dtd );

XmlDocument ex = new XmlDocument();
XmlTextReader tr = new XmlTextReader( "file://" + emailXML );
XmlValidatingReader vXR = new XmlValidatingReader(tr);

vXR.ValidationType = ValidationType.Auto;
vXR.ValidationEventHandler += new
ValidationEventHandler(HandleValidationEvents);
vXR.Schemas.Add(sc);

System.Diagnostics.Debug.WriteLine( "Loading ..." );
ex.Load(vXR);

XmlNamespaceManager nsmgr = new XmlNamespaceManager( ex.NameTable );
nsmgr.AddNamespace( "x", "http://localhost/xml" );
nsmgr.AddNamespace( "xs", "http://www.w3.org/2001/XMLSchema" );
XPathNavigator nav = ex.CreateNavigator();

// XmlNodeList nl =
ex.DocumentElement.SelectNodes("id(//x:Flow[@flowID='normal']/@processIDs)",
nsmgr);
XPathNodeIterator nl = nav.Select("id('WelcomeEmail')" );
while( nl.MoveNext() )
{
txtResults.Text += nl.Current.Name
txtResults.Text += "\r\n";
}

XslTransform xsl = new XslTransform();
xsl.Load( "file://" + emailTemplate );

XmlDocument resX = new XmlDocument();
XsltArgumentList al = new XsltArgumentList();
resX.Load( xsl.Transform( nav,al ));

System.IO.StringWriter s = new System.IO.StringWriter();
XmlTextWriter tw = new XmlTextWriter(s);
tw.Formatting = Formatting.Indented;
tw.Indentation = 2;
resX.WriteTo( tw );
txtResults.Text += s.ToString();
}
catch ( System.Xml.XmlException xe )
{
System.Diagnostics.Debug.Write( xe.ToString() + "\r\n" );
}

I have tried various combinations of the Selection functions all
unsuccessful.

================================================== ==========================
===========
XSLT

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:h="http://www.w3.org/1999/xhtml"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:x="http://localhost/xml" >

<xsl:output method="xml" indent="yes" />
<xsl:template match="/" >
<h:html>
<h:body>
<xsl:for-each select="x:Flows/x:Flow" >
<h:li><xsl:value-of select="." /></h:li>
</xsl:for-each>
<xsl:apply-templates select="*" />
</h:body>
</h:html>
</xsl:template>

<xsl:template match="x:Flow">
<h:li>Found Flow match <xsl:value-of select="@processIDs" /></h:li>
<xsl:for-each select="id('@processIDs')" >
<xsl:value-of select="." />
</xsl:for-each>
<h:p>how many did we find</h:p>
</xsl:template>

</xsl:stylesheet>

The stylesheet matches the Flow elements finds the @processIDs attributes
but the id function doesn't do anything.
================================================== ==========================
==========

"Oleg Tkachenko" <oleg@NO!SPAM!PLEASEtkachenko.com> wrote in message
news:ep**************@tk2msftngp13.phx.gbl...
Bill Eidson wrote:
I have a valid dtd which is used in validation via XMLValidatingReader and it does pick up mistakes
( To test it I broke it a couple of different ways and it was allways
detected. )

Still can't get XPathNavigator.Select or XmlNode.SelectNodes to work with XPATH id() function.


Well, should work. Make sure you are building XmlDocument or
XPathDocument via XmlValidatingReader. Or show us your code.
--
Oleg Tkachenko
XML Insider
http://www.tkachenko.com/blog

Nov 12 '05 #5

P: n/a
Bill Eidson wrote:
The stylesheet matches the Flow elements finds the @processIDs attributes
but the id function doesn't do anything.


Well, after more investigation now I see. It really doesn't work. I've
found 2 bugs involved.

First of all small but annoying bug - seems like id() function is unable
to convert its argument to string as it should per XSLT spec. So instead
of id(@processIDs) one should use id(string(@processIDs)).

Second one - it looks like XmlDocument is unable to cope with IDs when
namespaces involved. If you took default namespace declaration from your
XML, then id() function works, but not with namespace. Somehow
XmlDocument doesn't think elements in a namespace as eligible to be
referenced by ID. I didn't trace the problem though. Just use
XPathDocument instead, DOM is dead anyway :)

So, to make your code working use XPathDocument instead of XmlDocument
and convert id() function's argument to string explicitly via string()
function.
--
Oleg Tkachenko
XML Insider
http://www.tkachenko.com/blog

Nov 12 '05 #6

P: n/a
Hey Oleg, Thanks

The dtd version works hip hip hooray.
Both xslt and code version are happy campers.

This subtle bug in id function is a bit rude.

What did you mean by the DOM is dead... Is the model deprecated ?

Thanks again

bille

"Oleg Tkachenko" <oleg@NO!SPAM!PLEASEtkachenko.com> wrote in message
news:ev****************@TK2MSFTNGP09.phx.gbl...
Bill Eidson wrote:
The stylesheet matches the Flow elements finds the @processIDs attributes but the id function doesn't do anything.


Well, after more investigation now I see. It really doesn't work. I've
found 2 bugs involved.

First of all small but annoying bug - seems like id() function is unable
to convert its argument to string as it should per XSLT spec. So instead
of id(@processIDs) one should use id(string(@processIDs)).

Second one - it looks like XmlDocument is unable to cope with IDs when
namespaces involved. If you took default namespace declaration from your
XML, then id() function works, but not with namespace. Somehow
XmlDocument doesn't think elements in a namespace as eligible to be
referenced by ID. I didn't trace the problem though. Just use
XPathDocument instead, DOM is dead anyway :)

So, to make your code working use XPathDocument instead of XmlDocument
and convert id() function's argument to string explicitly via string()
function.
--
Oleg Tkachenko
XML Insider
http://www.tkachenko.com/blog

Nov 12 '05 #7

P: n/a
Bill Eidson wrote:
What did you mean by the DOM is dead... Is the model deprecated ?


That has been claimed by Mark Fussel in his ".NET Framework: What's New
in System.Xml for "Whidbey" session at PDC. See
http://www.25hoursaday.com/weblog/Pe...1-362b0a896f08
That doesn't mean XmlDocument is deprecated. It will be fully supported,
but the main focus is going to be XPathDocument (which is editable in
the next version), becuse it's more clean, robust, effective and better
fits XQuery data model.
Mark explained that at great length in microsoft.private.whidbey.xml
newsgroup
(http://communities.microsoft.com/new...dbey&slcid=us).
--
Oleg Tkachenko
XML Insider
http://www.tkachenko.com/blog

Nov 12 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.