Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C#] XPath met namespace werkt niet meer

Pagina: 1
Acties:

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 27-11 10:50

_Thanatos_

Ja, en kaal

Topicstarter
Ik weet dat hier al hele boeken over geschreven zijn, maar ik heb nog geen oplossing kunnen vinden die echt goed is en echt werkt. Vandaar nog maar es een poging. Ik heb een stukje XML:
XML:
1
2
3
4
<?xml version='1.0' encoding='iso-8859-1'?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="nl">
   en dan hier het document.
</html>

Ik laadt em in n doe de volgende XPath:
code:
1
//html

Maar helemaal niks. Uiteraard, want html heeft een namespace, en dat mag kennelijk niet ofzo. Haal ik de xmlns weg, dan werkt het als een zonnetje. Helaas heb ik niet de controle over wat voor xml er ingelezen wordt, en ik heb OOK NIET de controle over de xpath die ingetypt wordt. Gebruiker ziet <html> staan (of welk ander element dan ook) en daarop moet bijvoorbeeld //html gewoon werken. Simpel as that.

Ik heb wat zitten vogelen met de XmlNamespaceManager, door er een namespace zonder prefix aan toe te voegen. Ik heb geprobeerd het xmlns-attribuut in het XmlDocument knetterhard weg te flikkeren, en ook dat helpt niet. Het framework moet en zal een prefix OF geen namespace hebben, zo lijkt het.

Maar dat is niet goed genoeg voor mij. Ik wil bovenstaande combinatie, dus MET namespace en ZONDER gekke prefixes, werkend krijgen. Maar hoe?

日本!🎌


  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Gevonden op http://www.biglist.com/li...ives/200108/msg01232.html
You need to include the 'XCBL30.sox' namespace in your stylesheet, and
give it a prefix, e.g.:

XML:
1
2
3
4
5
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns:ord="XCBL30.sox">
...
</xsl:stylesheet>


Then you need to use this prefix in your XPath so that you can pick
elements in the 'XCBL30.sox' namespace:

XML:
1
2
3
4
5
6
7
8
<xsl:template match="/">
  <PO>
    <BuyerOrderNumber>
      <xsl:value-of select="/ord:Order/ord:OrderHeader
                              /ord:OrderNumber/ord:BuyerOrderNumber" />
    </BuyerOrderNumber>
  </PO>
</xsl:template>


In jouw geval zul je de namespace declaraties waarschijnlijk aan de namespace manager moeten geven, en dan kun je de prefixes als onderdeel van de qualified name gebruiken in je XPath-expressie.

Ik zie net dat je geen controle hebt over de XPath-expressie die gebruikt wordt; dan wordt het lastig, lijkt me.

[ Voor 5% gewijzigd door MrBucket op 21-10-2007 18:57 ]


  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 27-11 10:50

_Thanatos_

Ja, en kaal

Topicstarter
Persies, maar waarom toch die prefixes? Die staan helemaal niet in het source document. Dan is het toch volstrekt onlogisch dat die wél in de XPath moeten??

日本!🎌


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 30-11 06:38

Gerco

Professional Newbie

_Thanatos_ schreef op zondag 21 oktober 2007 @ 20:16:
Persies, maar waarom toch die prefixes? Die staan helemaal niet in het source document. Dan is het toch volstrekt onlogisch dat die wél in de XPath moeten??
Nee? Je kan namelijk zo'n Xml hebben:
XML:
1
2
3
4
5
<?xml version="1.0"?>
<root>
  <someElement xmlns="uri:someNamespace"/>
  <someElement xmlns="uri:someOtherNamespace"/>
</root>

Als je nu als XPath expressie opgeeft "//someElement", welke van de twee bedoel je dan?

Een element zonder prefix in een XPath expressie is gewoon shorthand voor "":element (oftwel, element in de default namespace). Als je iets anders bedoelde, had je dat moeten invoeren (prefix:element).

Wat je wel kan doen is een expressie als: "//*[local-name()='element']". Mooi is het niet, maar het werkt wel. Een non-namespace-aware parser gebruiken wil ook weleens helpen, die negeert dat hele namespace gebeuren volledig.

[ Voor 6% gewijzigd door Gerco op 21-10-2007 20:25 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 27-11 10:50

_Thanatos_

Ja, en kaal

Topicstarter
Als je nu als XPath expressie opgeeft "//someElement", welke van de twee bedoel je dan?
Allebei natuurlijk. Ze hebben immers beide geen prefix. Hoe wil je het anders doen? Als dát de XML is, en XPath daar niet mee om kan gaan, waar zit dan het probleem? In de XPath engine, lijkt me zo?

Kortom, er moet een oplossing voor zijn. Desnoods schrijf ik een XmlReader die default namespace-meuk negeert. Het geeft toch alleen maar problemen.

//edit
En inderdaad, dit lijkt een hoop problemen op te lossen:
C#:
1
2
3
4
5
6
public class NamespacelessXmlTextReader: XmlTextReader {
    public override string NamespaceURI {
        get { return null; }
    }
    public NamespacelessXmlTextReader(Stream stream) : base(stream) { }
}

Jaja, de XML-evangelisten zullen het er helemáál niet mee eens zijn, en ik zal er wel 43 regels mee breken, maar mijn motto is "het mot gewoon werken" en dat is hiermee gerechtvaardigd :P

[ Voor 34% gewijzigd door _Thanatos_ op 21-10-2007 21:06 ]

日本!🎌


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 30-11 06:38

Gerco

Professional Newbie

_Thanatos_ schreef op zondag 21 oktober 2007 @ 20:36:
Allebei natuurlijk. Ze hebben immers beide geen prefix. Hoe wil je het anders doen? Als dát de XML is, en XPath daar niet mee om kan gaan, waar zit dan het probleem? In de XPath engine, lijkt me zo?
Het gaat niet om de presentatie. Of een element een prefix heeft in het Xml document doet helemaal niet ter zake, nergens voor. Het gaat om de namespace van de elementen, niet om de prefix.

//someElement heeft aan dat je "":someElement zoekt. Als er dan alleen uri:someNamespace:someElement in je document aanwezig is, gaat hij die natuurlijk niet vinden. Of de namespace uri:someNamespace nu aangegeven wordt door prefix a, prefix b of door een xmlns= declaratie is niet belangrijk.

Overigens kun je de namespace awareness van de meeste Xml parsers gewoon uitzetten, die in .NET is daarop geen uitzondering (als ik het me goed herinner). Een eigen parser schrijven is onzinnig (en bovendien onbegonnen werk, tenzij je een hele kleine subset van Xml en XPath wilt ondersteunen.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 27-11 10:50

_Thanatos_

Ja, en kaal

Topicstarter
Ik wist dat je zo zou reageren, Gelco. Je zal vast gelijk hebben. In een wereld waar XML wordt gebruikt zoals het bedoeld is, heb je natuurlijk een punt. Maar in mijn wereld, waar het juíst om de presentatie draait, gaat je betoog helaas niet op.

Nu heb ik alleen nog een probleem als ik een element wil selecteren dat juist wél een prefix heeft. Dan zeurt de XPath dat de prefix niet gedefinieerd is, terwijl dat volgens mij wel zo is:
C#:
1
2
3
4
5
6
XPathExpression expression = XPathExpression.Compile(expressionString);
XPathNavigator navigator = document.CreateNavigator();
expression.SetContext(new XmlNamespaceManager(navigator.NameTable));
switch (expression.ReturnType) {
    //...
}

Met deze SetContext() call voer ik em toch de namespaces die nog wel gedefiniëerd zijn, toch?

日本!🎌


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 30-11 06:38

Gerco

Professional Newbie

Met de XmlTextReader.Namespaces Property kun je aangeven of je wilt dat de XmlTextReader de namespaces interpreteert. Misschien lost dat je probleem op.

Een andere oplossing is misschien om XmlTextReader te subclassen en dan alle namespace declaraties en prefixes eraf te slopen. Ik heb ook nog ergens een xslt liggen die alle namespaces van een document afstript, die kan ook van pas komen (als xslt een optie is).

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 27-11 10:50

_Thanatos_

Ja, en kaal

Topicstarter
Dat heb ik nu inmiddels opgelost, maar het gaat me nu weer ff om nodes die in de source wel een prefix hebben. Dus bijvoorbeeld:
XML:
1
2
3
4
<doc xmlns:x="http://example.com/doc"> 
   <parent/>
   <x:parent/>
</doc>

Kunnen queriën met XPath:
code:
1
//x:parent

Geeft nu dus een exception Namespace prefix 'x' is not defined.
Een iets ander probleem dan waarmee dit topic begon, maar nog steeds nauw verwant :)

日本!🎌

Pagina: 1