user602182 user602182 - 3 months ago 28
C# Question

Xelement.XPathSelectElement

I have the following XPath String

"(//DEAL_SETS/DEAL_SET/DEALS/DEAL/PARTIES/PARTY[ROLES/ROLE/
ROLE_DETAIL/PartyRoleType='Borrower'])
[(ROLES/PARTY_ROLE_IDENTIFIERS/PARTY_ROLE_IDENTIFIER/
PartyRoleIdentifier='1' or position() = 1)]/ROLES/ROLE/BORROWER/
RESIDENCES/RESIDENCE/ADDRESS/PostalCode[../../RESIDENCE_DETAIL/
BorrowerResidencyType='Current']"


which works when I put it in Altova XML Spy and gives me a result.

But when I use it directly as it is
Xelement.XPathSelectElement(XPath)
, it does not work, but what works is
Xelement.XPathSelectElement(collective, nameSpaceManager)
where collective is namesspace prefix (say named "ns") plus my XPath string.

But the problem is I have to change XPath string to something like this

"(//ns:DEAL_SETS/ns:DEAL_SET/ns:DEALS/ns:DEAL/ns:PARTIES/ns:PARTY[ns:ROLES/
ns:ROLE/ns:ROLE_DETAIL/ns:PartyRoleType='Borrower'])[(ns:ROLES/
ns:PARTY_ROLE_IDENTIFIERS/ns:PARTY_ROLE_IDENTIFIER/
ns:PartyRoleIdentifier='1' or position() = 1)]/ns:ROLES/
ns:ROLE/ns:BORROWER/ns:RESIDENCES/ns:RESIDENCE/
ns:ADDRESS/ns:PostalCode[../../ns:RESIDENCE_DETAIL/
ns:BorrowerResidencyType='Current']"


Is there any way to avoid having to put the namespace prefix (
ns:
) at each node.

Sorry for not posting the sample xml earlier,you may replicate the Party tag and its elements and fill up with false data, PartyRoleType gives me what party it is could be borrower,appraiser etc partyroleidentifier gives me a way to differentiate between two party with same partyroletypes for eg there could be 2 borrowers,the partyroleidentifier differentiates them as 1 and 2

<?xml version="1.0" encoding="utf-8"?>
<MESSAGE xmlns="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xxxxReferenceModelIdentifier="3.0.0.263.12" xsi:schemaLocation="http://www.example.org/schemas C:\Subversion\xxx_3_0.xsd">
<DEAL_SETS>
<DEAL_SET>
<DEALS>
<DEAL>
<PARTIES>
<PARTY>
<ROLES>
<ROLE>
<PARTY_ROLE_IDENTIFIERS>
<PARTY_ROLE_IDENTIFIER>
<PartyRoleIdentifier>1</PartyRoleIdentifier>
</PARTY_ROLE_IDENTIFIER>
</PARTY_ROLE_IDENTIIERS>
<BORROWER>
<RESIDENCES>
<RESIDENCE>
<ADDRESS>
<PostalCode>56236</PostalCode>
</ADDRESS>
</RESIDENCE>
</RESIDENCES>
</BORROWER>
<ROLE_DETAIL>
<PartyRoleType>Borrower</PartyRoleType>
</ROLE_DETAIL>
</ROLE>
</ROLES>
</PARTY>
</PARTIES>
</DEAL>
</DEALS>
</DEAL_SET>
</DEAL_SETS>
</MESSAGE>

Answer

According to the MSDN documentation, when you call AddNamespace for your namespace manager, you can use String.Empty as the prefix for your namespace URI. That should enable you to do an XPath expression without all those ns: prefixes.

Update:

OK, I remember encountering this issue before. The behavior of empty namespace prefixes in XPath expressions is not consistent with the rest of the .NET XML suite. There is some evidence that some Microsoft folks are aware of the issue. See this forum thread. I'll look for a while more for solutions, but I'm thinking that you'll have to make do with using namespace prefixes.

Update 2:

Feel free to vote on this Microsoft Connect Bug that I've just created. I see that they have closed similar bugs in the past, but none of them focused on usability concerns before. Maybe we'll get some traction with more votes.

Update 3:

Just some clarifications, my filed bug is not and never was about compliance with XPath standards, but rather about usability. No matter the standards, users need a way to make XPath queries with namespaced XML more succinct, and that is currently not supported. As far as standards support goes, XSLT 2.0 has a way to do XPath 2.0 with empty namespace prefixes associated with a namespace URI, and XMLSpy has that capability as well. The MSDN documentation claims that .NET has XPath 2.0 support, but the veracity of that claim is under dispute. One could argue that .NET is properly implementing XPath 1.0 by disallowing the modification of what an empty prefix represents.

Comments