Как выполнить замену всего, кроме комментариев в Java

1

У меня есть файл, обычно файлы XML. Я хочу заменить все вхождения "xy" на "p.q". Но во время этой замены я хочу игнорировать вхождения xy в комментариях().

Я пытался использовать String.replaceAll() для выполнения этой задачи.

Например:

<?xml version="1.0" encoding="UTF-8"?>
<name>This occurrence of x.y should be replaced</name>
<!-- This occurrence of x.y should not be replaced -->

Я попытался использовать String.replaceAll("x [\.] Y", "pq"), но я мог видеть, что вхождения в комментарии также заменяются

Я мог бы использовать другую альтернативу, по которой я могу читать файл за строкой и исключать строки, начинающиеся с комментариев, но меня интересует использование replaceAll()

Укажите способ, которым это может быть достигнуто.

  • 2
    Обязательная ссылка . Не используйте регулярные выражения, используйте один из многих анализаторов XML, предлагаемых JAXP.
  • 0
    Не используйте регулярные выражения для анализа XML. Самый простой подход в этом случае - использовать синтаксический анализатор XML.
Показать ещё 5 комментариев
Теги:

2 ответа

2
Лучший ответ

Хотя это не строго ответ, который вы ищете, у меня есть рекомендация.

Я бы рекомендовал использовать правильный XML-парсер, такой как Java DOM, для проверки и замены текста в ваших узлах, вместо того, чтобы иметь дело с вашим XML как сырой String. Что-то вроде этого должно заменить соответствующий текст на вашем узле, если они не являются комментарием.

File f = new File("your.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(f);

NodeList eList = doc.getElementsByTagName("*");
for (int e = 0; e < eList.getLength(); e++) {
    Node element = eList.item(e);
    NodeList nList = element.getChildNodes();
    for(int n = 0; n < nList.getLength(); n++){
        Node node = nList.item(n);
        if(node.getNodeType()==Node.TEXT_NODE){
            node.setNodeValue(node.getNodeValue().replace("x.y", "p.q")); 
        }
    }
}

Если проблема с памятью/эффективностью (например, когда ваш.xml огромен), вам лучше использовать SAX, который быстрее (немного больше кода) и не сохраняет XML в памяти.

Как только ваш Document будет отредактирован, вы, вероятно, захотите использовать трансформатор для создания подходящего вывода. (Официальное руководство здесь, реверанс комментария Бориса Спайдера)

Надеюсь это поможет.

Дальнейшее чтение;

  • 1
    Полностью согласен, +1. Хотя я должен сказать, что преобразование Document в String для его сохранения - это неправильно. Transformer специально разработан для этой задачи. Здесь есть учебник .
  • 0
    @BoristheSpider - Спасибо, хороший звонок, я заменю эту часть ответа.
Показать ещё 5 комментариев
1

Если вы используете регулярное выражение, опция должна использоваться для поиска заметок только для внешних комментариев:

(?s)x\.y(?!(?:(?!<!--).)+-->)

Как строка Java:

"(?s)x\\.y(?!(?:(?!<!--).)+-->)"

Использовал модификатор (?s) DOTALL для создания . также соответствуют новостям.

Тест в regexplanet (нажмите на Java)

  • 0
    Это прекрасно работает для комментариев XML. Я пытался применить тот же шаблон для исключения комментариев в файле .properties '#', используя x \\. Y (?! (?: (?! #).) +), Но он не работает. Текст в строке # также совпадает. Есть что-то, чего мне здесь не хватает
  • 0
    @AppanaSandeep Это другая задача. Если вы знаете, например, что одна строка не может быть длиннее, например 1024 попробуйте это в (?m) многострочном режиме: (?m)(?<!^ {0,1024}[#!].{0,1024})xy ; см. пример в regexplanet. Измените 1024 на желаемую максимальную длину строки. В большинстве разновидностей регулярных выражений нет квантификатора * доступного внутри внешнего вида, но в Java могут использоваться удивительно фигурные скобки.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню