এক্সএমএল শুধুমাত্র অবিলম্বে শিশুর উপাদান নাম দ্বারা পান

My question is: How can I get elements directly under a specific parent element when there are other elements with the same name as a "grandchild" of the parent element.

আমি জাভা ব্যবহার করছি DOM লাইব্রেরী এক্সএমএস বিশ্লেষণ করতে উপাদানগুলি এবং আমি চলছি কষ্ট। এখানে xml এর কিছু (একটি ছোট অংশ) আমি ব্যবহার করছি:


  
    
      
        
        
        
      
    
    
    
    
  

As you can see, there are two places you can place the element. Either in groups or outside groups. I really want it structured this way because it's more user-friendly.

Now, whenever I call notificationElement.getElementsByTagName("file"); it gives me all the elements, including those under the element. I handle each of these kinds of files differently, so this functionality is not desirable.

আমি দুটি সমাধান চিন্তা করেছি:

  1. Get the parent element of the file element and deal with it accordingly (depending on whether it's or .
  2. Rename the second element to avoid confusion.

Neither of those solutions are as desirable as just leaving things the way they are and getting only the elements which are direct children of elements.

আমি IMPO মন্তব্য করার জন্য এবং "শ্রেষ্ঠ" উপায় সম্পর্কে উত্তর করার জন্য উন্মুক্ত, কিন্তু আমি সত্যিই DOM সমাধানগুলিতে আগ্রহী কারণ এই বাকি প্রকল্পটি ব্যবহার করছে. ধন্যবাদ।

33
যোগ সম্পাদিত
মতামত: 1
আমি উল্লেখ করা উচিত যে এটি শুধুমাত্র একটি বড় xml ফাইলের একটি ছোট অংশ :) এটি পাঠযোগ্য করতে চেয়েছিলেন।
যোগ লেখক kentcdodds, উৎস
@ অ্যালেক্স অর্গ.উইএসসিওডোমা XPath সমর্থন করে না; তিনি একটি ভিন্ন লাইব্রেরি ব্যবহার করতে চাইবেন, যেমন- org.jdom.xpath, এর জন্য ... যদিও আমি পুরোপুরি একমত যে এটি আরো মার্জিত পদ্ধতির মত।
যোগ লেখক Charles Duffy, উৎস
উভয় নোডের তালিকা পেতে এবং তাদের পৃথকভাবে ব্যবহার করার জন্য আপনি কেন XPath ব্যবহার করবেন না? //গ্রুপ/গ্রুপ/ফাইল এবং //বিজ্ঞপ্তি/ফাইল তাদের কাছে যথেষ্ট হবে। অথবা আপনি শুধু এক XPath চান তাদের সব পেতে?
যোগ লেখক Alex, উৎস
javax.xml.xpath হল জাভা স্ট্যান্ডার্ড, তাই আমি মনে করতে পারি যে এটি খুব সহজেই ব্যবহার করতে পারে, শুধু এই সহজ টাস্কের জন্য JDom পেতে হবে না।
যোগ লেখক Alex, উৎস
কেন এই সংগ্রহটি তৈরি না করে আপনি সরাসরি হ'ল হ'ল, যেমন: "নোডিলিস্ট নোডস = এলিমেন্ট .getChildNodes (); for (int i = 0; i
যোগ লেখক Dmitry, উৎস

8 উত্তর

আমি বুঝতে পারছি মে মাসে এটির একটি সমাধান পাওয়া যায় @ কেেন্টডডডস কিন্তু আমার কাছে এটি একটি মোটামুটি অনুরূপ সমস্যা ছিল যা আমি এখন পেয়েছি, আমার মনে হয় (সম্ভবত আমার ব্যবহারযোগ্য নয়, কিন্তু আপনার মধ্যে নেই), একটি সমাধান।

আমার xml ফরম্যাটের একটি খুব সরল উদাহরণ নীচে দেখানো হয়েছে: -

<?xml version="1.0" encoding="utf-8"?>

    
        
            
            
        
    
    
    


আপনি এই snippet থেকে আশা করতে পারেন হিসাবে, আমি চাই যে ফরম্যাটের [সম্পর্ক] নোডের জন্য নেস্টিং এর N- স্তরের থাকতে পারে, তাই স্পষ্টত আমি Node.getChildNodes() সঙ্গে ছিল সমস্যা ছিল যে আমি সব স্তরের সমস্ত নোড পেয়েছিলাম ছিল অনুক্রম, এবং নোডের গভীরতা হিসাবে কোন ধরণের ইঙ্গিত ছাড়াই।

API </> এ দেখুন একটি> কিছুদিনের জন্য, আমি লক্ষ্য করেছি কিছু অন্যান্য পদ্ধতি আছে যা কিছু ব্যবহার হতে পারে: -

একসঙ্গে, এই দুটি পদ্ধতি একটি নড এর অবিলম্বে বংশধর উপাদান সব পেতে প্রয়োজন ছিল সবকিছু প্রস্তাব লাগে। নিম্নলিখিত jsp কোডটি এই বাস্তবায়ন কিভাবে একটি মোটামুটি মৌলিক ধারণা দিতে হবে। জেএসপি জন্য দুঃখিত। আমি এখন একটি মটরশুটি এই প্রারম্ভে করছি কিন্তু একটি সম্পূর্ণরূপে কাজ সংস্করণ থেকে বাছাই পৃথক কোড তৈরি করার সময় ছিল না।

<%@page import="javax.xml.parsers.DocumentBuilderFactory,
                javax.xml.parsers.DocumentBuilder,
                org.w3c.dom.Document,
                org.w3c.dom.NodeList,
                org.w3c.dom.Node,
                org.w3c.dom.Element,
                java.io.File" %><% 
try {

    File fXmlFile = new File(application.getRealPath("/") + "/utils/forms-testbench/dom-test/test.xml");
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(fXmlFile);
    doc.getDocumentElement().normalize();

    Element docEl = doc.getDocumentElement();       
    Node childNode = docEl.getFirstChild();     
    while( childNode.getNextSibling()!=null ){          
        childNode = childNode.getNextSibling();         
        if (childNode.getNodeType() == Node.ELEMENT_NODE) {         
            Element childElement = (Element) childNode;             
            out.println("NODE num:-" + childElement.getAttribute("num") + "
\n" ); } } } catch (Exception e) { out.println("ERROR:- " + e.toString() + "
\n"); } %>

এই কোডটি নিম্নোক্ত আউটপুটটি প্রদান করবে, যা প্রারম্ভিক রুট নোডের সরাসরি শিশু উপাদান দেখাবে।

NODE num:-1
NODE num:-1.1
NODE num:-1.2

আশা করি যে কেউ এইভাবে সাহায্য করবে। প্রাথমিক পোস্ট জন্য Cheers

19
যোগ
একটি সত্যিই সহজ, সহজ এবং পরিষ্কার সমাধান জন্য +1 আপনি এই প্রযুক্তির সাথে একটি জন্য লুপ ব্যবহার করতে পারেন, এটি মার্জিত এবং সংরক্ষণের জন্য: জন্য (নোড এন = docEl.getFirstChild (); n! = Null; n = n.getNextSibling ()) </কোড>।
যোগ লেখক krispy, উৎস
প্রশ্নটি আরেকটি সম্পূর্ণ গ্রহণযোগ্য উত্তর প্রদানের জন্য +1। :)
যোগ লেখক kentcdodds, উৎস
Cheers @kentcdodds আসলে একটি আকর্ষণীয় সমস্যার মোকাবেলা এবং এটি আসলে অন্য সমাধান খুঁজে বের করে। মোটামুটি খুশি আমি বিদ্যমান কোড পোর্ট না ছাড়া org.w3c.dom ব্যবহার করতে অবিরত করতে পারেন। প্রশ্নের জন্য ধন্যবাদ!
যোগ লেখক BizNuge, উৎস

আপনি এই জন্য XPath ব্যবহার করতে পারেন, তাদের পেতে দুটি পদ্ধতি ব্যবহার করে এবং তাদের ভিন্নভাবে প্রক্রিয়া করুন

To get the nodes direct children of use //notification/file and for the ones in use //groups/group/file.

এটি একটি সহজ নমুনা:

public class SO10689900 {
    public static void main(String[] args) throws Exception {
        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = db.parse(new InputSource(new StringReader("\n" + 
                "  \n" + 
                "    \n" + 
                "      \n" + 
                "        \n" + 
                "        \n" + 
                "        \n" + 
                "      \n" + 
                "    \n" + 
                "    \n" + 
                "    \n" + 
                "    \n" + 
                "  \n" + 
                "")));
        XPath xpath = XPathFactory.newInstance().newXPath();
        XPathExpression expr1 = xpath.compile("//notification/file");
        NodeList nodes = (NodeList)expr1.evaluate(doc, XPathConstants.NODESET);
        System.out.println("Files in //notification");
        printFiles(nodes);

        XPathExpression expr2 = xpath.compile("//groups/group/file");
        NodeList nodes2 = (NodeList)expr2.evaluate(doc, XPathConstants.NODESET);
        System.out.println("Files in //groups/group");
        printFiles(nodes2);
    }

    public static void printFiles(NodeList nodes) {
        for (int i = 0; i < nodes.getLength(); ++i) {
            Node file = nodes.item(i);
            System.out.println(file.getAttributes().getNamedItem("location"));
        }
    }
}

এটা আউটপুট উচিত:

Files in //notification
location="C:\valid\file.txt"
location="C:\valid\file.xml"
location="C:\valid\file.doc"
Files in //groups/group
location="C:\valid\directory\"
location="C:\this\file\doesn't\exist.grr"
location="C:\valid\file\here.txt"
13
যোগ
আমি পাথ দ্বারা একটি উপাদান অনুসন্ধান করার উপায় খুঁজছি <�কোড> root/etc/foo এবং অবশেষে এটি তৈরি করুন, অথবা এটির অস্তিত্ব না থাকলে পিতা বা মাতা নয়। আমি শিশুদের নোডের মধ্যে একটি লুপ জন্য ভালো কিছু ব্যবহার করতে পারি? আমি শুধুমাত্র প্রথম ঘটনা সম্পর্কে যত্ন নিই।
যোগ লেখক Tomáš Zato, উৎস
একটি ভাল উত্তর মনে হয়, এবং ভবিষ্যতে আমি DOM থেকে XPath থেকে সরে যেতে পারি। কিন্তু এই প্রকল্পের জন্য এই শেষ জিনিসটি আমাকে করতে হবে এবং আমি DOM এর সাথে থাকা চাই। যাইহোক, যদি আমি DOM এর জন্য অন্য কোনও উত্তর পাই না, তবে আমি আপনাকে গ্রহণ করব কারণ এটি একটি উত্তম উত্তর। কোনও ভাবেই, আপনি যেমন একটি পুঙ্খানুপুঙ্খ উত্তর জন্য একটি +1 পেতে।
যোগ লেখক kentcdodds, উৎস
আমি একটি ভাল সমাধান পাওয়া যায় নি। কারণ যে কাজ করা অসম্ভব কারণ চাইল্ড নোড নোটিশ </কোড> উপাদানটি অনেক আছে আমি যদিও প্রশ্ন উত্তর। আপনার উত্তরের উত্তরের জন্য ধন্যবাদ। ভবিষ্যতে আমি সত্যিই XPath এর দিকে নজর দেব।
যোগ লেখক kentcdodds, উৎস
আপনি যদি DOM- এর সাথে চলাফেরা করতে চান তাহলে আপনাকে নোডএলস্ট ব্যবহার করে ((নোড) বিজ্ঞপ্তি এলেমেন্ট) এর পুনরাবৃত্তির প্রয়োজন হবে .getChildNodes() এবং কেবলমাত্র তার নাম রাখুন <�কোড> ফাইল </কোড>। মূলত আপনাকে এটি করার জন্য সব বিজ্ঞপ্তি </কোড> ট্যাগ খুঁজে পেতে হবে। একই কোডটি গ্রুপ ট্যাগগুলির জন্য করা প্রয়োজন।
যোগ লেখক Alex, উৎস

Well, the DOM solution to this question is actually pretty simple, even if it's not too elegant When I iterate through the filesNodeList which is returned when I call notificationElement.getElementsByTagName("file"); I just check whether the parent node's name is "notification." If it isn't then I ignore it because that will be handled by the element. Here's my code solution:

for (int j = 0; j < filesNodeList.getLength(); j++) {
  Element fileElement = (Element) filesNodeList.item(j);
  if (!fileElement.getParentNode().getNodeName().equals("notification")) {
    continue;
  }
  ...
}
12
যোগ
সাবাস !!!!!!!!!!
যোগ লেখক madhairsilence, উৎস
@ জেনস্রোলেসেন, যদি আপনি আইটেমটি একটি উপাদান হিসাবে নিক্ষেপ করে দ্বিতীয় লাইনের কথা বলছেন, তাহলে এটি DOM এর পার্সিং এর উপর নির্ভর করে ... যদি না হয় তবে আপনি কি বলতে চান?
যোগ লেখক kentcdodds, উৎস
নিক্ষেপ করা নিরাপদ?
যোগ লেখক Janus Troelsen, উৎস
হ্যাঁ, এটাই আমার বোঝা
যোগ লেখক Janus Troelsen, উৎস
'GetParentNode' ফাংশন (এবং 'getNodeName') 'নোড' ইন্টারফেসে পাওয়া যায়। তাই শুধু নাম চেক করার জন্য, কোন ঢাল প্রয়োজন হয়। (এবং শুধু নিরাপত্তার জন্য "সমীকরণ" এর সমতুল্য পরিবর্তন করুন। বিভাজন (...))
যোগ লেখক Justin, উৎস
আপনি শুধু উপাদান.getChildNodes() মাধ্যমে পুনরাবৃত্তি না কেন?
যোগ লেখক FINDarkside, উৎস

আপনি DOM API- র সাথে থাকুন

NodeList nodeList = doc.getElementsByTagName("notification")
    .item(0).getChildNodes();

// get the immediate child (1st generation)
for (int i = 0; i < nodeList.getLength(); i++)
    switch (nodeList.item(i).getNodeType()) {
        case Node.ELEMENT_NODE:

            Element element = (Element) nodeList.item(i);
            System.out.println("element name: " + element.getNodeName());
           //check the element name
            if (element.getNodeName().equalsIgnoreCase("file"))
            {

               //do something with you "file" element (child first generation)

                System.out.println("element name: "
                    + element.getNodeName() + " attribute: "
                    + element.getAttribute("location"));

            }
    break;

}

আমাদের প্রথম টাস্ক একটি উপাদান "বিজ্ঞপ্তি" পেতে (এই ক্ষেত্রে প্রথম -আইটিম (0) -) এবং তার সব শিশুদের:

NodeList nodeList = doc.getElementsByTagName("notification")
    .item(0).getChildNodes();

(পরবর্তীতে আপনি সমস্ত উপাদানগুলি ব্যবহার করে সমস্ত উপাদানের সাথে কাজ করতে পারেন)।

"বিজ্ঞপ্তিকর" প্রত্যেক শিশুর জন্য:

for (int i = 0; i < nodeList.getLength(); i++)

আপনি প্রথমে এটি একটি উপাদান কিনা তা দেখতে তার ধরনের পেতে:

switch (nodeList.item(i).getNodeType()) {
    case Node.ELEMENT_NODE:
        //.......
        break;  
}

যদি মামলা হয়, তাহলে আপনার সন্তানদের "ফাইল" পেয়েছেন, যারা নাটকগুলি "নোটিফিকেশন" নয়

এবং আপনি তাদের চেক আউট করতে পারেন:

if (element.getNodeName().equalsIgnoreCase("file"))
{

   //do something with you "file" element (child first generation)

    System.out.println("element name:"
        + element.getNodeName() + " attribute: "
        + element.getAttribute("location"));

}

এবং outut হয়:

element name: file
element name:file attribute: C:\valid\file.txt
element name: file
element name:file attribute: C:\valid\file.xml
element name: file
element name:file attribute: C:\valid\file.doc
4
যোগ
সমাধান জন্য ধন্যবাদ আমার সমাধান এই অনুরূপ, কিন্তু আমি সব শিশুদের মাধ্যমে না তাড়াহুড়া না কারণ এই উপাদান যা আমি আমার প্রশ্ন প্রদর্শন না শুধুমাত্র তথ্য ওভারলোড এড়ানোর জন্য আরো অনেক শিশু আছে। যাইহোক, আবার ধন্যবাদ একটি ভাল উত্তর জন্য +1।
যোগ লেখক kentcdodds, উৎস
@ কেটেনডডডস.আমার উত্তরটি আপডেট করুন। আপনি দেখতে পারেন, "আইডি" ব্যবহার না করেই এক্সএমএল দিয়ে কাজ করলে আপনি কেবল "getElementsByTagName" এবং "getChildNodes" দিয়ে খেলতে পারবেন। আপনি DOM সঙ্গে সরাসরি কাজ করার সময় আপনার মতামত অন্যান্য উত্তর আছে না। স্যার আপনি DOM সঙ্গে থাকা আছে। সমাধান যাই হোক না কেন সম্ভবত এটি একটি নির্দিষ্ট নোড শিশুদের (আপনার ক্ষেত্রে অ্যাক্সেস এই ক্ষেত্রে "বিজ্ঞপ্তি ")। আমার সমাধান অপ্রয়োজনীয় কাজ পরিত্যাগ করার জন্য টাইপ নোড পরীক্ষা করে। কিন্তু আপনি এখনও সব শিশুদের পুনরুক্তি করতে হবে। কোন" আইডি "না হলে কি হবে: আপনি একটি সংগ্রহের সঙ্গে শেষ।
যোগ লেখক arthur, উৎস
@arthur (অফ-বিষয়) যে সমস্ত পবিত্র প্রেমের জন্য, অনুগ্রহপূর্বক একটি কাল এবং পরবর্তী বাক্যটির প্রথম অক্ষরের মধ্যে কিছু সাদা প্যাটার্ন রাখুন। এই বিশুদ্ধ পাগল!
যোগ লেখক klaar, উৎস

I had the same problem in one of my projects and wrote a little function which will return a List containing only the immediate children. Basically it checks for each node returned by getElementsByTagName if it's parentNode is actually the node we are searching childs of:

public static List getDirectChildsByTag(Element el, String sTagName) {
        NodeList allChilds = el.getElementsByTagName(sTagName);
        List res = new ArrayList<>();

        for (int i = 0; i < allChilds.getLength(); i++) {
            if (allChilds.item(i).getParentNode().equals(el))
                res.add((Element) allChilds.item(i));
        }

        return res;
    }

কেটেনেকডড্ডের গৃহীত উত্তরগুলি ভুল রিটার্নস (যেমন, দাদা) ফেরত পাঠাবে যদি "নোটিফিকেশন" নামে একটি চাইল্ডডোড থাকে - যেমন- ফিরে আসছে grandchilds যখন উপাদান "গ্রুপ" নাম "বিজ্ঞপ্তি" হবে। আমি আমার প্রজেক্টে সেটআপের মুখোমুখি হচ্ছি, যা আমার ফাংশনে এসেছিল।

2
যোগ

আমি tagName দ্বারা নোড মান পেতে এই ফাংশনটি লিখেছিলাম, শীর্ষ স্তরে সীমাবদ্ধ

public static String getValue(Element item, String tagToGet, String parentTagName) {
    NodeList n = item.getElementsByTagName(tagToGet);
    Node nodeToGet = null;
    for (int i = 0; i
0
যোগ

আমি একটি সম্পর্কিত সমস্যা সম্মুখীন যেখানে আমি শুধুমাত্র তাত্ক্ষণিক শিশু নোড প্রক্রিয়া প্রয়োজন যদিও "ফাইল" নোডের চিকিত্সার অনুরূপ। আমার সমাধান জন্য, আমি এলিমেন্ট এর পিতা বা মাতা নোডের সাথে তুলনা করা হয় যে উপাদানটি তাৎক্ষণিক সন্তান হয় কিনা তা নির্ধারণ করার জন্য এটি প্রক্রিয়া করা হচ্ছে।

NodeList fileNodes = parentNode.getElementsByTagName("file");
for(int i = 0; i < fileNodes.getLength(); i++){
            if(parentNode.equals(fileNodes.item(i).getParentNode())){
                if (fileNodes.item(i).getNodeType() == Node.ELEMENT_NODE) {

                    //process the child node...
                }
            }
        }
0
যোগ

একটি চমৎকার LINQ সমাধান আছে:

For Each child As XmlElement In From cn As XmlNode In xe.ChildNodes Where cn.Name = "file"
    ...
Next
0
যোগ