О, дорогой, это сложно ...
Прежде всего, вы не отметили свой вопрос версией XPath.Обычно люди, которые не знают о версиях XPath, используют древнюю версию 1.0, поэтому я сделаю это предположение: извините, если это не так.
В XPath 1.0 - функция, которой присваивается набор узлов икоторая ожидает, что строка использует строковое значение первого узла в наборе узлов, взятое в порядке документа.
В вашем запросе
normalize-space(string(//emp))
//emp
выбирает набор узлов,который содержит один узел, поэтому string () принимает строковое значение этого узла.Строковое значение узла элемента является объединением всех его потомков текстового узла.Функция normalize-space удаляет начальные и конечные пробелы и нормализует внутреннее пространство до одного символа пробела.
Вы показали ваш XML в отступной форме как
<company>
<emp>
<dept>Acct</dept>
<salary>1000</salary>
и т. Д., Так что это разумноожидать, что пробел между элементами образует часть строкового значения элемента <emp>
.Но вы не сказали нам, как документ был проанализирован и превращен в дерево узлов.Парсеры часто предоставляют несколько вариантов того, как это сделать, в частности, как обрабатывать пробелы между узлами элементов.Большинство сохраняют пробелы по умолчанию, если, возможно, не существует схемы или DTD, которые сообщают анализатору, что пробелы незначительны.Известно, что синтаксический анализатор MSXML от Microsoft удаляет пробелы по умолчанию, что создает значительные проблемы при использовании XML для представления описательных документов, но на самом деле облегчает жизнь людям, использующим XML для такого рода недокументированных данных.
Ваш синтаксический анализатор по тем или иным причинам (мы не можем сказать), похоже, удалил пробел между узлами элемента.Ни один запрос XPath не вернет его снова.У вас могут быть варианты при создании документа для сохранения пробела;это зависит от инструментов, которые вы используете.
Ваш второй вопрос касается удаления одного из элементов ввода.Это выходит за рамки XPath.XPath может только выбирать узлы из входных данных, но никак не может их изменять.Чтобы изменить дерево, вам нужен XSLT или XQuery.
Ваша попытка решить проблему с //emp[not(descendant::gender)]
безнадежно обречена, потому что это будет выбирать только тех сотрудников, у которых нет элемента-потомка с именем gender
.Похоже, вы угадываете семантику, а не используете спецификацию или учебное пособие.