2012-12-28 13 views
6

से अधिक पुनरावृति करने के लिए मैं की तर्ज पर एक XML संरचना है:कैसे बढ़ावा में XML संरचना :: property_tree

<root> 
<SomeElement> 
    <AnotherElement> 
    <ElementIWant x="1" y="1"/> 
    </AnotherElement> 
</SomeElement> 
<SomeElement> 
    <AnotherElement> 
    <ElementIWant x="1" y="1"/> 
    <ElementIWant x="2" y="1"/> 
    <ElementIWant x="3" y="1"/> 
    </AnotherElement> 
</SomeElement> 
</root> 

जो एक boost::property_tree में पढ़ा जा रहा है, 1..Many<SomeElement> रों रहे हैं, और फिर उस तत्व के भीतर एक मनमाना गहराई में हो सकता है 1..Many<ElementIWant> रों

वहाँ आदेश है कि वे appea में <ElementIWant> सीधे से अधिक पुनरावृति करने के लिए (एक पाश में) एक रास्ता है डॉक्टर में आर?

मैं equal_range

void iterateOverPoints() 
{ 
    const char* test = 
    "<?xml version=\"1.0\" encoding=\"utf-8\"?><root>" 
     "<SomeElement>" 
     "<AnotherElement>" 
     "<ElementIWant x=\"1\" y=\"1\"/>" 
     "</AnotherElement>" 
     "</SomeElement>" 
     "<SomeElement>" 
     "<AnotherElement>" 
     "<ElementIWant x=\"1\" y=\"1\"/>" 
     "<ElementIWant x=\"2\" y=\"1\"/>" 
     "<ElementIWant x=\"3\" y=\"1\"/>" 
     "</AnotherElement>" 
     "</SomeElement>" 
    "</root>"; 

    boost::property_tree::ptree message; 
    std::istringstream toParse(test); 
    boost::property_tree::read_xml(toParse,result_tree); 

    //Now we need to locate the point elements and set the x/y accordingly. 
    std::pair< boost::property_tree::ptree::const_assoc_iterator, 
       boost::property_tree::ptree::const_assoc_iterator > result = 
     message.equal_range("ElementIWant"); 

    for(boost::property_tree::ptree::const_assoc_iterator it = result.first; 
      it != result.second; ++it) 
    { 
     std::cout << it->first << " : "; 
     const boost::property_tree::ptree& x = it->second.get_child("<xmlattr>.x"); 
     const boost::property_tree::ptree& y = it->second.get_child("<xmlattr>.y"); 
     std::cout << x.get_value<int>() << "," << y.get_value<int>() << "\n"; 
    } 

    return; 
} 

को देखा लेकिन यह नोड्स (जो मुझे लगता है क्योंकि equal_range आपूर्ति पेड़ नोड के स्तर पर काम करता है) कौन सा मेरे ऊपर सवाल के लिए लाता है वापस जाने के लिए असफल रहा है है। ..

+0

क्या आपने 'equal_range (" someElement.AnotherElement.ElementIwant ") का प्रयास किया था;'? निश्चित नहीं है कि कुछ ऐसा होने पर क्या होगा जब कुछ एलीमेंट की दो प्रतियां होंगी। –

+0

अतीत से विस्फोट! @TreborRude मुझे लगता है कि उस समय जिस तरह से मैं चाहता था उसमें व्यवहार नहीं करता था, या यह काम नहीं करता था। शायद पुस्तकालय को ऐसा करने के बाद बढ़ाया गया है - लेकिन मैं इस समय कोड के उस क्षेत्र से बहुत दूर हूं। :) फिर भी सुझाव के लिए धन्यवाद। – Caribou

उत्तर

4

सभी तत्वों को सीधे पुन: सक्रिय करना संभव नहीं है; the documentation says

पूरे पेड़ पर फिर से प्रयास करने का कोई तरीका नहीं है।

अब, आप रिकर्सन का उपयोग कर सकते हैं और प्रत्येक स्तर पर एसटीएल एल्गोरिदम लागू कर सकते हैं; यह नीचे मेरी नमूना में एक भी पाश में ऐसा करने का आपकी आवश्यकता से मेल नहीं खाती है, लेकिन यह काम करता है करता है:

template <typename InputIt, typename OutputIt, typename Compare> 
void collect(InputIt first, InputIt last, OutputIt dest, Compare comp) 
{ 
    typedef typename std::iterator_traits<InputIt>::reference reference; 

    std::copy_if (
     first, last, dest, 
     [comp] (reference what) { return comp(what.first); }); 

    std::for_each (
     first, last, 
     [dest, comp] (reference what) { collect(what.second.begin(), what.second.end(), dest, comp); }); 
} 


std::vector<std::pair<std::string, ptree>> match; 

collect(
    xml.begin(), xml.end(), std::back_inserter(match), 
    [] (const std::string& key) { return key == "ElementIWant"; }); 

for (auto pair: match) 
{ 
    std::cout << pair.first << std::endl; 
} 

यहाँ एक संस्करण है कि है "पूरी तरह से" पुनरावर्ती और उपस्थिति का क्रम बनाए रखने के है:

template <typename InputIt, typename OutputIt, typename Compare> 
void collect_recursive(InputIt first, InputIt last, OutputIt dest, Compare comp) 
{ 
    typedef typename std::iterator_traits<InputIt>::reference reference; 

    if (first == last) 
    { 
     return; 
    } 

    auto begin = first->second.begin(); 
    auto end = first->second.end(); 

    if (begin != end) 
    { 
     collect_recursive (begin, end, dest, comp); 
    } 

    if (comp (first->first)) 
    { 
     dest = *first; 
    } 

    collect_recursive (++first, last, dest, comp); 
} 
+0

मुझे उम्मीद थी कि कुछ चाल हो सकती है, लेकिन मैं अब भी इसी तरह के साथ खेल रहा हूं। मैं देखूंगा कि क्या मैंने उपर्युक्त किया है - उत्तर के लिए Thx। – Caribou

+0

बीटीडब्ल्यू इसे स्वीकार करेगा क्योंकि यह सही जवाब है जिसे मैं संदेह करता हूं लेकिन ऐसा करने से पहले थोड़ी देर के लिए खेलना चाहता हूं :) – Caribou

+0

@ करिबू वास्तव में, मैं भी अपनी तरफ थोड़ा सा खेल रहा हूं, मैं एक "पूरी तरह से" रिकर्सिव संस्करण, क्योंकि इस पहले प्रयास में, उपस्थिति का क्रम संरक्षित नहीं है! – piwi

संबंधित मुद्दे