2013-03-01 14 views
5

Próbuję użyć groovy, aby po prostu dodać węzeł do a w określonej lokalizacji. Moje źródło schematu wygląda toGroovy: jak parsować xml i zachować przestrzenie nazw i schematyLocations

<s1:RootNode 
    xmlns:s1="http://localhost/s1schema" 
    xmlns:s2="http://localhost/s2schema" 
    xsi:schemaLocation="http://localhost/s1schema s1schema.xsd 
    http://localhost/s2schema s2schema.xsd"> 
<s1:aParentNode> 
    <s2:targetNode> 
    <s2:childnode1 /> 
    <s2:childnode2 /> 
    <s2:childnode3 /> 
    <s2:childnode4 /> 
</s2:targetNode> 
</s1:aParentNode> 
</s1:RootNode> 

Chciałbym po prostu dodać nowy węzeł dziecko inline z innymi te, do ich wyjścia

<s1:RootNode 
    xmlns:s1="http://localhost/s1schema" 
    xmlns:s2="http://localhost/s2schema" 
    xsi:schemaLocation="http://localhost/s1schema s1schema.xsd 
    http://localhost/s2schema s2schema.xsd"> 
<s1:aParentNode>  
    <s2:targetNode> 
    <s2:childnode1 /> 
    <s2:childnode2 /> 
    <s2:childnode3 /> 
    <s2:childnode4 /> 
    <s2:childnode5 >value</s2:childnode5> 
    </s2:targetNode> 
    </s1:aParentNode> 
</s1:RootNode> 

Aby to zrobić, mam następujący prosty porywające skryptu

def data = 'value' 
def root = new XmlSlurper(false,true).parseText(sourceXML) 
     root.'aParentNode'.'topNode'.appendNode{ 
      's2:childnode5' data 
     } 
groovy.xml.XmlUtil.serialize(root); 

Jednak gdy to robię, przestrzenie nazw i schematy, które są stosowane do węzła głównego, są usuwane. a przestrzeń nazw, ale nie lokalizacja schematu jest dodawana do każdego z węzłów podrzędnych.

powoduje to problemy z zatwierdzaniem w dół.

Jak po prostu przetworzyć ten xml. nie wykonuje sprawdzania poprawności i pozostawić plik XML w niezmienionej postaci i dodać pojedynczy węzeł o określonej przestrzeni nazw?

Jedna uwaga: przetwarzamy wiele komunikatów i nie znam z góry zewnętrznej większości przestrzeni nazw (s1 w powyższym przykładzie), ale nawet z tym, jestem po prostu wyczucie techniki, która jest "głupsza" przetwarzanie xml

Dzięki!

Odpowiedz

2

Najpierw musiałem dodać xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance", aby zdefiniować przestrzeń nazw xsi. Bez tego otrzymałem wyjątek SAXParseException dla niezwiązanego przedrostka xsi.

Dodatkowo, sprawdziłem, czy question pomyślnie dołącza węzeł xml z podanym obszarem do istniejącego dokumentu.

Wreszcie, musieliśmy wykorzystać StreamingMarkupBuilder do obejścia ruchu przestrzeni nazw. Zasadniczo, serializer domyślnie przenosi odnośniki nazw do pierwszego węzła, który faktycznie używa przestrzeni nazw. W twoim przypadku przeniesienie atrybutu s2 namespace do tagu "targetNode". Poniższy kod generuje pożądane wyniki, ale nadal będziesz musiał znać poprawne przestrzenie nazw, które będą używane do tworzenia instancji StreamingMarkupBuilder.

def root = new XmlSlurper(false, true).parseText(sourceXML) 
def data = '<s2:childnode5 xmlns:s2="http://localhost/s2schema">value</s2:childnode5>' 
def xmlFragment = new XmlSlurper(false, true).parseText(data) 
root.'aParentNode'.'targetNode'.appendNode(xmlFragment); 

def outputBuilder = new StreamingMarkupBuilder() 
String result = XmlUtil.serialize(outputBuilder.bind { 
    mkp.declareNamespace('s1':"http://localhost/s1schema") 
    mkp.declareNamespace('s2':"http://localhost/s2schema") 
    mkp.yield root } 
) 
+0

To pytanie dotyczy również niektórych z tych samych problemów: http://stackoverflow.com/questions/227447/how-do-i-print-a-groovy-node-with-namespace-preserved – purgatory101

+0

Dzięki. Natknąłem się na takie rozwiązanie, jedynym problemem, jaki mam, jest to, że nie wiem, które schematy są zdefiniowane lub które należy zdefiniować przed przetworzeniem, więc nie będę w stanie "mkp.declareNamespace (..)" Ponadto musimy być w stanie obsłużyć zmiany w schemacie bez zmian w tym komponencie. Tak więc moja jedyna odpowiedź byłaby czymś, co definiuje te schematy jako jakąś mapę lub parsuje je z xml przed wykonaniem pracy.Chociaż jest nieco więcej linii kodu, wydaje się bardziej oczywiste, co dzieje się przy użyciu DOM do parsowania xml w java – Beta033

0

XMLSlurper (lub XMLParser) nie obsługuje nazw jeśli ustawić drugi parametr konstruktora:

XmlSlurper (boolean validating, boolean namespaceAware) 

false:

def root = new XmlSlurper(false, false).parseText(sourceXML) 

Bez ustawiania namespaceAware false, I również zmierzył się z dziwnym bahwaniem parsera. Po ustawieniu wartości false, pozostawia kod XML bez zmian, bez zmiany przestrzeni nazw.