سؤال

I am trying to find out the total number of elements of a specific name that exist in an Xml document using VB. Should be a simple enough task but I've hit a problem.

I can make the following code work but can't pass the element name as a string (In the original code I am doing this from an array that I want to loop through), I don't receive an error in visual studio, at compile time or during run time, it just returns zero quantity. I have cut the original code down to show just the section I am having an issue with.

The following code works.

    Dim xmlDoc = XDocument.Load("c:\test\xmlFile.xml")
    myXMLRowCount = xmlDoc.Root.Elements.<AIOWEB_tPriceBand>.Count()
    MsgBox(myXMLRowCount)

The only example I can find for passing a variable as the element is by removing the .<> and replacing with (myVariable) - as the code below shows, but the example I have seen this on is for Element not Elements and doesn't appear to work the same (unless I'm missing a step / character in the command structure).

    Dim xmlDoc = XDocument.Load("c:\test\xmlFile.xml")
    Dim myXmlElement As String = "AIOWEB_tPriceBand"
    myXMLRowCount = xmlDoc.Root.Elements(myXmlElement).Count()
    MsgBox(myXMLRowCount)
  • edit *

Here's a cut down example of one of the xml files in question. I have tested it here with the above lines of code and again the direct reference works (shows 5 elements) but the second example with the variable returns 0 elements.

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:od="urn:schemas-microsoft-com:officedata">
    <xsd:schema>
        <xsd:element name="dataroot">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element ref="AIOWEB_tPriceBand" minOccurs="0" maxOccurs="unbounded"/>
                </xsd:sequence>
                <xsd:attribute name="generated" type="xsd:dateTime"/>
            </xsd:complexType>
        </xsd:element>
        <xsd:element name="AIOWEB_tPriceBand">
            <xsd:annotation>
                <xsd:appinfo>
                    <od:index index-name="ProductCode" index-key="ProductCode " primary="no" unique="no" clustered="no"/>
                </xsd:appinfo>
            </xsd:annotation>
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="ProductCode" minOccurs="0" od:jetType="text" od:sqlSType="nvarchar">
                        <xsd:simpleType>
                            <xsd:restriction base="xsd:string">
                                <xsd:maxLength value="50"/>
                            </xsd:restriction>
                        </xsd:simpleType>
                    </xsd:element>
                    <xsd:element name="MinQty" minOccurs="0" od:jetType="longinteger" od:sqlSType="int" type="xsd:int"/>
                    <xsd:element name="MaxQty" minOccurs="0" od:jetType="longinteger" od:sqlSType="int" type="xsd:int"/>
                    <xsd:element name="UnitPrice" minOccurs="0" od:jetType="currency" od:sqlSType="money" type="xsd:double"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>
    <dataroot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" generated="2014-01-16T12:02:35">
        <AIOWEB_tPriceBand>
            <ProductCode>0000000000001</ProductCode>
            <MinQty>1</MinQty>
            <MaxQty>0</MaxQty>
            <UnitPrice>0.01</UnitPrice>
        </AIOWEB_tPriceBand>
        <AIOWEB_tPriceBand>
            <ProductCode>0000000000002</ProductCode>
            <MinQty>1</MinQty>
            <MaxQty>0</MaxQty>
            <UnitPrice>0.01</UnitPrice>
        </AIOWEB_tPriceBand>
        <AIOWEB_tPriceBand>
            <ProductCode>0000000000003</ProductCode>
            <MinQty>1</MinQty>
            <MaxQty>0</MaxQty>
            <UnitPrice>0.01</UnitPrice>
        </AIOWEB_tPriceBand>
        <AIOWEB_tPriceBand>
            <ProductCode>0000000000004</ProductCode>
            <MinQty>1</MinQty>
            <MaxQty>0</MaxQty>
            <UnitPrice>0.01</UnitPrice>
        </AIOWEB_tPriceBand>
        <AIOWEB_tPriceBand>
            <ProductCode>0000000000005</ProductCode>
            <MinQty>1</MinQty>
            <MaxQty>0</MaxQty>
            <UnitPrice>0.01</UnitPrice>
        </AIOWEB_tPriceBand>
    </dataroot>
</root>
هل كانت مفيدة؟

المحلول

The AIOWEB_tPriceBand elements are not located directly under the root element. Instead, they are actually located under the /root/dataroot element.

The reason that the first code sample works is because it is reading the xmlDoc.Root.Elements.<AIOWEB_tPriceBand> elements. You'll notice that it is not accessing the AIOWEB_tPriceBand elements directly under Root. Instead, it's accessing them from Root.Elements, which is actually the collection of all of the child elements of the Root element. Since dataroot is a child of the Root element, it will look for them under there. To make the first code sample mimic the second one, you would have needed to write it this way:

' Won't work because it looks for /root/AIOWEB_tPriceBand
myXMLRowCount = xmlDoc.Root.<AIOWEB_tPriceBand>.Count()

The less confusing way to have written it, to make it work properly, would have been like this:

' Will work because it looks for /root/dataroot/AIOWEB_tPriceBand
myXMLRowCount = xmlDoc.Root.<dataroot>.<AIOWEB_tPriceBand>.Count()

Now that it's more clear why it was that the first example was actually working, now it should be more clear how to get the second example to work:

myXMLRowCount = xmlDoc.Root.<dataroot>.Elements(myXmlElement).Count()

Alternatively, if you don't care where, exactly, in the document structure, that the AIOWEB_tPriceBand elements actually exist, and all you want to do is get a total count of them, where ever in the document they happen to be, then you can simply search for any descendants of the root by that name, rather than specifying the path down through the dataroot element:

myXMLRowCount = xmlDoc.Root...<AIOWEB_tPriceBand>.Count()

Or, by string:

myXMLRowCount = xmlDoc.Root.Descendants(myXmlElement).Count()

I should also mention that you really ought to be using MessageBox.Show rather than the old VB6-style MsgBox method.

نصائح أخرى

I think instead of myXMLRowCount = xmlDoc.Root.Elements(myXmlElement).Count() you want myXMLRowCount = xmlDoc.Root.Element("dataroot").Elements(myXmlElement).Count(), to match the hierarchy in your input sample. Or you need at least myXMLRowCount = xmlDoc.Root.Elements().Elements(myXmlElement).Count().

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top