Как вставить / заменить тег XML в XmlDocument?

У меня есть XmlDocument в java, созданный с помощью парсера Weblogic XmlDocument.

Я хочу заменить содержимое тега в XMLDocument моими собственными данными или вставить тег, если его там нет.

<customdata>
   <tag1 />
   <tag2>mfkdslmlfkm</tag2>
   <location />
   <tag3 />
</customdata>

Например, я хочу вставить URL-адрес в тег местоположения:

<location>http://something</location>

но в остальном оставьте XML как есть.

В настоящее время я использую XMLCursor:

    XmlObject xmlobj = XmlObject.Factory.parse(a.getCustomData(), options);
    XmlCursor xmlcur = xmlobj.newCursor();

    while (xmlcur.hasNextToken()) {
      boolean found = false;
      if (xmlcur.isStart() && "schema-location".equals(xmlcur.getName().toString())) {
        xmlcur.setTextValue("http://replaced");
        System.out.println("replaced");
        found = true;
      } else if (xmlcur.isStart() && "customdata".equals(xmlcur.getName().toString())) {
        xmlcur.push();
      } else if (xmlcur.isEnddoc()) {
        if (!found) {
          xmlcur.pop();
          xmlcur.toEndToken();
          xmlcur.insertElementWithText("schema-location", "http://inserted");
          System.out.println("inserted");
        }

      }
      xmlcur.toNextToken();
    }

Я попытался найти «быстрый» способ xquery сделать это, поскольку XmlDocument имеет метод execQuery, но не нашел его очень легким.

Есть ли у кого-нибудь способ лучше, чем этот? Это кажется немного сложным.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
0
5 019
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

У вас должно получиться сделать это с query.

пытаться

 fn:replace(string,pattern,replace)

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

Я все еще хочу, чтобы был более простой способ, который был бы столь же эффективным?

replace не изменяет документы, он просто заменяет текстовые вхождения в строке и возвращает строку.

Martin Probst 20.10.2008 19:26

Как насчет объектно-ориентированного подхода? Вы можете десериализовать XML в объект, установить значение местоположения для объекта, а затем сериализовать обратно в XML.

XStream упрощает это.

Например, вы должны определить основной объект, которым в вашем случае является CustomData (я использую общедоступные поля, чтобы упростить пример):

public class CustomData {
  public String tag1;
  public String tag2;
  public String location;
  public String tag3;
}

Затем вы инициализируете XStream:

XStream xstream = new XStream();
// if you need to output the main tag in lowercase, use the following line
xstream.alias("customdata", CustomData.class);  

Теперь вы можете создать объект из XML, установить поле местоположения для объекта и повторно сгенерировать XML:

CustomData d = (CustomData)xstream.fromXML(xml);
d.location = "http://stackoverflow.com";
xml = xstream.toXML(d);

Как это звучит?

Ответ принят как подходящий

Как насчет подхода на основе XPath? Мне нравится этот подход, поскольку его логика очень проста для понимания. Код в значительной степени самодокументируется.

Если ваш xml-документ доступен вам как объект org.w3c.dom.Document (как возвращают большинство парсеров), вы можете сделать что-то вроде следующего:

// get the list of customdata nodes
NodeList customDataNodeSet = findNodes(document, "//customdata" );

for (int i=0 ; i < customDataNodeSet.getLength() ; i++) {
  Node customDataNode = customDataNodeSet.item( i );

  // get the location nodes (if any) within this one customdata node
  NodeList locationNodeSet = findNodes(customDataNode, "location" );

  if (locationNodeSet.getLength() > 0) {
    // replace
    locationNodeSet.item( 0 ).setTextContent( "http://stackoverflow.com/" );
  }
  else {
    // insert
    Element newLocationNode = document.createElement( "location" );
    newLocationNode.setTextContent("http://stackoverflow.com/" );
    customDataNode.appendChild( newLocationNode );
  }
}

А вот вспомогательный метод findNodes, который выполняет поиск XPath.

private NodeList findNodes( Object obj, String xPathString )
  throws XPathExpressionException {

  XPath xPath = XPathFactory.newInstance().newXPath();
  XPathExpression expression = xPath.compile( xPathString );
  return (NodeList) expression.evaluate( obj, XPathConstants.NODESET );
}

Если вы не знаете схему, решение XStream, вероятно, не подходит. По крайней мере, XStream сейчас на вашем радаре, может пригодиться в будущем!

Другие вопросы по теме