Заменить значение элемента XML? Регулярное выражение Sed?

EXEC sp_serveroption 'YOURSERVERNAME', 'DATA ACCESS', TRUE

SELECT  *
INTO    #tmpTable
FROM    OPENQUERY(YOURSERVERNAME, 'EXEC db.schema.sproc 1')
5
задан James Adams 28 August 2009 в 16:31
поделиться

4 ответа

Хорошо, поэтому я укусил пулю и нашел время, чтобы написать программу Java, которая делает то, что я хочу. Ниже приведен рабочий метод, вызываемый моим методом main (), который выполняет эту работу, на случай, если это будет полезно кому-то еще в будущем:

/**
 * Takes an input XML file, replaces the text value of the node specified by an XPath parameter, and writes a new
 * XML file with the updated data.
 * 
 * @param inputXmlFilePathName
 * @param outputXmlFilePathName
 * @param elementXpath
 * @param elementValue
 * @param replaceAllFoundElements
 */
public static void replaceElementValue(final String inputXmlFilePathName,
                                       final String outputXmlFilePathName,
                                       final String elementXpathExpression,
                                       final String elementValue,
                                       final boolean replaceAllFoundElements)
{
    try
    {
        // get the template XML as a W3C Document Object Model which we can later write back as a file
        InputSource inputSource = new InputSource(new FileInputStream(inputXmlFilePathName));
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        Document document = documentBuilderFactory.newDocumentBuilder().parse(inputSource);

        // create an XPath expression to access the element's node
        XPathFactory xpathFactory = XPathFactory.newInstance();
        XPath xpath = xpathFactory.newXPath();
        XPathExpression xpathExpression = xpath.compile(elementXpathExpression);

        // get the node(s) which corresponds to the XPath expression and replace the value
        Object xpathExpressionResult = xpathExpression.evaluate(document, XPathConstants.NODESET);
        if (xpathExpressionResult == null)
        {
            throw new RuntimeException("Failed to find a node corresponding to the provided XPath.");
        }
        NodeList nodeList = (NodeList) xpathExpressionResult;
        if ((nodeList.getLength() > 1) && !replaceAllFoundElements)
        {
            throw new RuntimeException("Found multiple nodes corresponding to the provided XPath and multiple replacements not specified.");
        }
        for (int i = 0; i < nodeList.getLength(); i++)
        {
            nodeList.item(i).setTextContent(elementValue);
        }

        // prepare the DOM document for writing
        Source source = new DOMSource(document);

        // prepare the output file
        File file = new File(outputXmlFilePathName);
        Result result = new StreamResult(file);

        // write the DOM document to the file
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.transform(source, result);
    }
    catch (Exception ex)
    {
        throw new RuntimeException("Failed to replace the element value.", ex);
    }
}

Я запускаю программу следующим образом:

$ java -cp xmlutility.jar com.abc.util.XmlUtility input.xml output.xml '//name/text()' JAMES
4
ответ дан 13 December 2019 в 05:39
поделиться

sed не будет простым инструментом для использования многострочной замены. Их можно реализовать с помощью команды N и некоторой рекурсии, проверяя после чтения в каждой строке, было ли найдено закрытие тега ... но это некрасиво, и вы никогда не вспомните об этом.

Конечно, на самом деле самым безопасным будет анализ xml и замена тегов, но если вы знаете, что не столкнетесь с какими-либо проблемами, вы можете попробовать следующее:

perl -p -0777 -e 's@<xyz>.*?</xyz>@<xyz>new-value</xyz>@sg' <xml-file>

Нарушение этого:

  • -p указывает ему выполнить цикл по вводу, а print
  • -0777 указывает ему использовать конец файла в качестве разделителя входных данных, так что он получит все за один slurp
  • -e означает то, что я хочу, чтобы вы сделали

И сама замена:

  • используйте @ в качестве разделителя, чтобы не было необходимости экранировать /
  • , используйте *? , нежадную версию, чтобы сопоставить всего лишь возможно, поэтому мы не дойдем до последнего появления в файле
  • , используйте модификатор s , чтобы разрешить . ] сопоставление новой строки (для получения значений многострочного тега)
  • используйте модификатор g , чтобы сопоставить шаблон несколько раз

Tada! Результат будет выведен на стандартный вывод - как только вы убедитесь, что он делает то, что вы хотите, добавьте параметр -i , чтобы указать ему отредактировать файл на месте.

в файле
  • используйте модификатор s , чтобы разрешить . сопоставление новой строки (для получения значений многострочного тега)
  • используйте модификатор g , чтобы сопоставить шаблон несколько раз
  • Tada! Результат будет выведен на стандартный вывод - как только вы убедитесь, что он делает то, что вы хотите, добавьте параметр -i , чтобы указать ему отредактировать файл на месте.

    в файле
  • используйте модификатор s , чтобы разрешить . сопоставление новой строки (для получения значений многострочного тега)
  • используйте модификатор g , чтобы сопоставить шаблон несколько раз
  • Tada! Результат будет выведен на стандартный вывод - как только вы убедитесь, что он делает то, что вы хотите, добавьте параметр -i , чтобы указать ему отредактировать файл на месте.

    6
    ответ дан 13 December 2019 в 05:39
    поделиться

    Ненавижу скептически относиться к XML, но XML не является обычным. С регулярным выражением, вероятно, будет больше проблем, чем оно того стоит. См. Здесь для получения дополнительной информации: Использование регулярных выражений C # для замены содержимого XML-элементов

    В конце концов, ваша мысль о простой программе Java может быть хорошей. Преобразование XSLT может быть проще, если вы хорошо знаете XSLT. Если вы знаете Perl ... это путь, ИМХО.

    Сказав это, если вы выберете Regex и ваша версия sed поддерживает расширенные регулярные выражения, вы можете сделать его многострочным с помощью / g. Другими словами, поместите / g в конец регулярного выражения, и он будет соответствовать вашему шаблону, даже если они находятся на нескольких строках.

    Также. предложенное вами регулярное выражение является «жадным». Он будет захватывать самую большую группу символов, потому что ". " будет соответствовать от первого вхождения до последнего. Вы можете сделать его «ленивым», изменив подстановочный знак на «. ?». Если поставить вопросительный знак после звездочки, это означает, что он соответствует только одному набору из до.

    будет соответствовать от первого до последнего появления. Вы можете сделать его «ленивым», изменив подстановочный знак на «. ?». Если поставить вопросительный знак после звездочки, это означает, что он соответствует только одному набору из до.

    будет соответствовать от первого до последнего появления. Вы можете сделать его «ленивым», изменив подстановочный знак на «. ?». Если поставить вопросительный знак после звездочки, это означает, что он соответствует только одному набору из до.

    2
    ответ дан 13 December 2019 в 05:39
    поделиться

    Я пытался сделать то же самое и наткнулся на скрипт [gu] awk, который его добился.

    BEGIN { FS = "[<|>]" }
    {
        if ($2 == "xyz") {
            sub($3, "replacement")      
        }
        print
    }
    
    0
    ответ дан 13 December 2019 в 05:39
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: