2008-08-19 3 views
3

У меня есть XmlDocument в java, созданный с помощью парсера Weblogic XmlDocument.Вставить/заменить тег XML в 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 метод, но не нашел его очень легко.

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

ответ

4

Как насчет подхода на основе 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); 
} 
0

Вы должны быть в состоянии сделать это с query

попробовать

fn:replace(string,pattern,replace) 

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

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

+1

replace не изменяет документы, он просто заменяет текстовые вхождения в строке и возвращает строку. – 2008-10-20 15:26:40

1

Как насчет объектно-ориентированного подхода? Вы можете десериализовать 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); 

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

1

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

Смежные вопросы