@@ -764,6 +764,18 @@ private static string AttributeToXpathElement(XAttribute attr)
764764 }
765765 }
766766
767+ private static string GetElementPathStep ( XElement element )
768+ {
769+ if ( element == null )
770+ return string . Empty ;
771+ string step = element . Name . LocalName ;
772+ if ( element . FirstAttribute != null )
773+ {
774+ step += AttributeToXpathElement ( element . FirstAttribute ) ;
775+ }
776+ return step ;
777+ }
778+
767779 private static ( string step , string patchForParent ) GetElementPathStep (
768780 XElement element ,
769781 XElement parent ,
@@ -777,23 +789,18 @@ private static (string step, string patchForParent) GetElementPathStep(
777789 if ( parent == null )
778790 return ( string . Empty , string . Empty ) ;
779791 string step = "" ;
780- if ( patchForParent == "" )
781- patchForParent = $ "{ element . Name . LocalName } ";
782- List < XAttribute > attributes = [ ] ;
783- if ( element . FirstAttribute != null )
784- {
785- patchForParent += AttributeToXpathElement ( element . FirstAttribute ) ;
786- }
792+ patchForParent += GetElementPathStep ( element ) ;
787793 IEnumerable < XElement > matches = parent . XPathSelectElements ( patchForParent ) ;
794+ List < XAttribute > ? attributes = null ;
788795 if ( matches . Count ( ) == 1 && matches . First ( ) == element )
789796 {
790797 step = patchForParent ;
791798 }
792799 else
793800 {
794- attributes = element . Attributes ( ) . ToList ( ) ;
801+ attributes = element . Attributes ( ) . Skip ( 1 ) . ToList ( ) ;
795802 }
796- if ( attributes . Count > 0 )
803+ if ( attributes ? . Count > 0 )
797804 {
798805 string xpath = $ "{ patchForParent } ";
799806 if ( pathOptions . UseAllAttributes )
@@ -881,33 +888,53 @@ private static string GenerateXPath(XElement element, PathOptions pathOptions)
881888 }
882889 if ( step == "" )
883890 {
884- var siblings = parent . Elements ( ) . ToList ( ) ;
885- string xpathWithSiblings = "" ;
886- int index = siblings . IndexOf ( current ) ;
887- if ( index + 1 < siblings . Count )
888- {
889- XElement sibling = siblings [ index + 1 ] ;
890- ( step , xpathWithSiblings ) = GetElementPathStep (
891- sibling ,
892- parent ,
893- doc ,
894- pathOptions ,
895- $ "{ patchForParent } /following-sibling::{ sibling . Name . LocalName } "
896- ) ;
897- }
898- if ( step . StartsWith ( "//" ) )
891+ if ( path . Length > 0 )
899892 {
900- return step ;
893+ if ( parent . XPathSelectElements ( $ "{ patchForParent } /{ path } ") . Count ( ) == 1 )
894+ {
895+ step = GetElementPathStep ( current ) ;
896+ }
901897 }
902- else if ( step == "" )
898+ if ( string . IsNullOrEmpty ( step ) )
903899 {
904- if ( siblings . Count == 1 )
900+ var siblings = parent . Elements ( ) . ToList ( ) ;
901+ string xpathWithSiblings = "" ;
902+ int index = siblings . IndexOf ( current ) ;
903+ if ( index > 0 )
905904 {
906- step = $ "{ patchForParent } ";
905+ XElement sibling = siblings [ index - 1 ] ;
906+ ( step , xpathWithSiblings ) = GetElementPathStep ( sibling , parent , doc , pathOptions ) ;
907+ if ( ! string . IsNullOrEmpty ( step ) )
908+ {
909+ step += $ "/following-sibling::{ patchForParent } ";
910+ }
907911 }
908- else
912+ if ( string . IsNullOrEmpty ( step ) )
909913 {
910- step = $ "{ patchForParent } [{ index + 1 } ]";
914+ if ( index + 1 < siblings . Count )
915+ {
916+ XElement sibling = siblings [ index + 1 ] ;
917+ ( step , xpathWithSiblings ) = GetElementPathStep ( sibling , parent , doc , pathOptions ) ;
918+ if ( ! string . IsNullOrEmpty ( step ) )
919+ {
920+ step += $ "/preceding-sibling::{ patchForParent } ";
921+ }
922+ }
923+ }
924+ if ( step . StartsWith ( "//" ) )
925+ {
926+ return step ;
927+ }
928+ else if ( string . IsNullOrEmpty ( step ) )
929+ {
930+ if ( siblings . Count == 1 )
931+ {
932+ step = $ "{ patchForParent } ";
933+ }
934+ else
935+ {
936+ step = $ "{ patchForParent } [{ index + 1 } ]";
937+ }
911938 }
912939 }
913940 }
0 commit comments