Я бы проверил, чтобы убедиться, что вы на самом деле получаете списки только узлов типа ATTR, а не элементов или их комбинации. Я не использовал XPathExpression, однако он может интерпретировать путь «// @ *» как «любой элемент с атрибутом», а не «все атрибуты» (что, как я ожидаю, вы имеете в виду). Если первый равен true, а ваш корневой узел имеет атрибут, он будет отображаться в результирующем списке узлов из запроса и по определению [корневой узел] .getParentNode () == null, создающий ваш NPE.
Кроме того, если вы выбираете с помощью запроса узлы элементов, а не узлы attr, выражение n.getTextContent () будет искать текстовое содержимое, а не значение атрибута (опять же, вероятная причина, ведущая к вашему NPE, если корневой узел находится в списке, так как большинство корневых узлов не имеют текстового содержимого), кроме того, попытка удаления атрибута была бы запрещена (что вы в действительности не намереваетесь).
Так что, если вы получаете узлы элементов вместо узлов атрибутов, то вам следует взглянуть на карту атрибутов, а затем изменить ее, и если вам нужно просмотреть все атрибуты, вам может быть лучше просто написать Depth-First -Поиск, глядя на DOM и выполняя изменения там.