问:
How to populate a treeview from a XML file with multiple child nodes?
I´m trying to populate a TreeView component in VB.NET from a XML file. It´s a large XML file and I chopped it up in order to give you guys an idea about how it is structured. I´m new to VB.NET so I´m having a hard time to figure this out. Below there´s an image of the order I expect this data to be shown in the TreeView, and I added some arrows so you can understand where the data is supposed to come from in the XML structure.

I found and tried to adapt a code I got from a Microsoft tutorial, but it´s based on a much simpler XML structure and it´s not working with my file.

The arrows in the image are being shown out of synch with the XML tags & nodes but my goal was to avoid the arrows and rectangles overlaping each other making the picture unreadable.

When we have a node named "Cutter" it´s a different type of component, and more than one may be comprised within the current "Cutter" or "Holder" node, so they are separated by the "Reference" tag. If it´s named "Holder" it´s another component type on the tool stackup... Every new tool starts with an element named "Tool".

Below the picture what I´m trying to do in the code:

Tree View Explanation

```<code>Private Sub btnSearchTLS_Click(sender As Object, e As EventArgs) Handles btnSearchTLS.Click

        Try
            ' SECTION 1. Create a DOM Document and load the XML data into it.
            Dim dom As New XmlDocument()
            dom.Load(txtFileOpenTLS_2.Text)

            ' SECTION 2. Initialize the treeview control.
            tviewToolIDs.Nodes.Clear()
            tviewToolIDs.Nodes.Add(New TreeNode(dom.DocumentElement.Name))
            Dim tNode As New TreeNode()
            tNode = tviewToolIDs.Nodes(0)

            ' SECTION 3. Populate the TreeView with the DOM nodes.
            AddNode(dom.DocumentElement, tNode)
            tviewToolIDs.ExpandAll()

        Catch xmlEx As XmlException
            MessageBox.Show(xmlEx.Message)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

    Private Sub AddNode(ByRef inXmlNode As XmlNode, ByRef inTreeNode As TreeNode)
        Dim xNode As XmlNode
        Dim tNode As TreeNode
        Dim nodeList As XmlNodeList
        Dim i As Integer

        ' Loop through the XML nodes until the leaf is reached.
        ' Add the nodes to the TreeView during the looping process.
        If inXmlNode.HasChildNodes() Then
            nodeList = inXmlNode.ChildNodes
            For i = 0 To nodeList.Count - 1
                xNode = inXmlNode.(i)
                inTreeNode.Nodes.Add(New TreeNode(xNode.Name))
                tNode = inTreeNode.Nodes(i)
                AddNode(xNode, tNode)
            Next
        Else
            ' Here you need to pull the data from the XmlNode based on the
            ' type of node, whether attribute values are required, and so forth.
            inTreeNode.Text = (inXmlNode.OuterXml).Trim
        End If
    End Sub
</code>```

Here´s the XML file:

```<code>    <?xml version="1.0"?>
<ToolLibrary Version="7.3">
    <Tools>
    <Tool ID="100004" Units="Millimeter">
      <Description>100004</Description>
      <Teeth>1</Teeth>
      <Type>Turning</Type>
      <Cutter>
        <Reference ID="12140 - N123G2-0318-0008">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Torneamento - Insertos paramétricos</ToolID>
          <EntityName>12140 - N123G2-0318-0008</EntityName>
          <Origin>
            <X>34.2</X>
            <Y>0</Y>
            <Z>-82.3</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>-90</Y>
            <Z>0</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Cutter>
      <Holder>
        <Reference ID="12135 - C5-570-32-LF">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12135 - C5-570-32-LF</EntityName>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="12139 - 570-32L123G18B130A">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12139 - 570-32L123G18B130A</EntityName>
          <Origin>
            <X>21</X>
            <Y>0</Y>
            <Z>-42</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Holder>
      <DrivenPoint ID="1">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>35</X>
        <Y>0</Y>
        <Z>-83.1</Z>
      </DrivenPoint>
      <DrivenPoint ID="2">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>31.82</X>
        <Y>0</Y>
        <Z>-83.1</Z>
      </DrivenPoint>
      <CutterCompensation ID="1">0.8</CutterCompensation>
      <CutterCompensation ID="2">0.8</CutterCompensation>
    </Tool>
    <Tool ID="100171" Units="Millimeter">
      <Description>100171</Description>
      <Teeth>1</Teeth>
      <Type>Turning</Type>
      <Cutter>
        <Reference ID="12349 - CNMG120412">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Torneamento - Insertos paramétricos</ToolID>
          <EntityName>12349 - CNMG120412</EntityName>
          <Origin>
            <X>-35.8</X>
            <Y>0</Y>
            <Z>-291.8</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>-5</Y>
            <Z>0</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Cutter>
      <Holder>
        <Reference ID="11977 - C6-390.410-100-110A">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>11977 - C6-390.410-100-110A</EntityName>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="11978 - C6-570-2C-60-148-40L">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>11978 - C6-570-2C-60-148-40L</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-110</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="11979 - SL-PCLNL-40-12HP">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>11979 - SL-PCLNL-40-12HP</EntityName>
          <Origin>
            <X>-10</X>
            <Y>0</Y>
            <Z>-258</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Holder>
      <DrivenPoint ID="1">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>-37</X>
        <Y>0</Y>
        <Z>-293</Z>
      </DrivenPoint>
      <DrivenPoint ID="2">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>-37</X>
        <Y>0</Y>
        <Z>-293</Z>
      </DrivenPoint>
      <CutterCompensation ID="1">1.2</CutterCompensation>
      <CutterCompensation ID="2">1.2</CutterCompensation>
    </Tool>
    <Tool ID="100178" Units="Millimeter">
      <Description>100178</Description>
      <Teeth>8</Teeth>
      <Type>Milling</Type>
      <Cutter>
        <Reference ID="10084 - R90MT-12-05-RM">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>44</X>
            <Y>0</Y>
            <Z>-614</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM1">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>31.112698</X>
            <Y>-31.112698</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>-45</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM11">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>31.112698</X>
            <Y>31.112698</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>45</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM12">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>0</X>
            <Y>-44</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>-90</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM13">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>0</X>
            <Y>44</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>90</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM14">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>-31.112698</X>
            <Y>31.112698</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>135</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM15">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>-44</X>
            <Y>0</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>180</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>-31.1127</X>
            <Y>-31.1127</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>-135</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Cutter>
      <Holder>
        <Reference ID="11974 - C8-390.410-100 120A">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>11974 - C8-390.410-100 120A</EntityName>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="12001 - C8-391.01-80 065">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12001 - C8-391.01-80 065</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-120</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="12001 - C8-391.01-80 065">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12001 - C8-391.01-80 065</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-185</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="12002 - C8-391.05-CD-32-320">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12002 - C8-391.05-CD-32-320</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-250</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10707 - FCM-D100-32-11">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>10707 - FCM-D100-32-11</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-570</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Holder>
      <DrivenPoint ID="1">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>0</X>
        <Y>0</Y>
        <Z>-620</Z>
      </DrivenPoint>
      <DrivenPoint ID="2">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>0</X>
        <Y>0</Y>
        <Z>-620</Z>
      </DrivenPoint>
      <CutterCompensation ID="1">50</CutterCompensation>
      <CutterCompensation ID="2">50</CutterCompensation>
    </Tool>
    <Tool ID="100192" Units="Millimeter">
      <Description>100192</Description>
      <Teeth>1</Teeth>
      <Type>Milling</Type>
      <Cutter>
        <Reference ID="10087 - 880-05-03-05H-C-GM">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10087 - 880-05-03-05H-C-GM</EntityName>
          <Origin>
            <X>-7.9</X>
            <Y>0</Y>
            <Z>-233.5</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>180</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10088 - 880-05 03 W05H-P-GM">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10088 - 880-05 03 W05H-P-GM</EntityName>
          <Origin>
            <X>12</X>
            <Y>0</Y>
            <Z>-233.5</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Cutter>
      <Holder>
        <Reference ID="12007 - C4-390.410-100-090A">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12007 - C4-390.410-100-090A</EntityName>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="12033 - 880-D2500C4-04">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12033 - 880-D2500C4-04</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-90</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Holder>
      <DrivenPoint ID="1">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>0</X>
        <Y>0</Y>
        <Z>-234</Z>
      </DrivenPoint>
    </Tool>
    <Tool ID="801154" Units="Millimeter">
      <Description>801154</Description>
      <Teeth>1</Teeth>
      <Type>Turning</Type>
      <Cutter>
        <Reference ID="11325 - MKI-176807-13_4.4">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Torneamento - Insertos 3D</ToolID>
          <EntityName>11325 - MKI-176807-13_4.4</EntityName>
          <Origin>
            <X>-5.18</X>
            <Y>0</Y>
            <Z>-225</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Cutter>
      <Holder>
        <Reference ID="12016 - 392.410-100-ASHL-32">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12016 - 392.410-100-ASHL-32</EntityName>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="11328 - MKS-366807-18">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>11328 - MKS-366807-18</EntityName>
          <Origin>
            <X>-8</X>
            <Y>0</Y>
            <Z>-55</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Holder>
      <DrivenPoint ID="2">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>-2.980037</X>
        <Y>0</Y>
        <Z>-225</Z>
      </DrivenPoint>
      <DrivenPoint ID="1">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>-7.380037</X>
        <Y>0</Y>
        <Z>-225</Z>
      </DrivenPoint>
      <CutterCompensation ID="1">1.5</CutterCompensation>
      <CutterCompensation ID="2">1.5</CutterCompensation>
    </Tool>
  </Tools>
 </ToolLibrary>
</code>```

What do I have to do in the code above (Considering it´s the right code - Feel free to come up with a new approach) to make my TreeView to be populated like shown in the image?

I´m sorry for asking for a thing possibly already covered, I did a search and could not find something that could work with my XML example.

Tks in advance,

Daniel

答:
Use this.

Const FILENAME As String = "C:\joy\Web.config.xml"
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Try
            ' SECTION 1. Create a DOM Document and load the XML data into it

```<code>        Dim reader As New StreamReader(FILENAME, System.Text.Encoding.UTF8)
        Dim dom As XDocument = XDocument.Load(reader)            ' SECTION 2. Initialize the treeview control.
        Dim rootNode As New TreeNode(dom.Root.Name.LocalName)
        TreeView1.Nodes.Clear()
        TreeView1.Nodes.Add(rootNode)
        Dim ch = dom.Root.Elements()

        For Each obj As XElement In ch
            Dim chNode As New TreeNode(obj.Name.LocalName)
            addNode(obj, chNode, rootNode)
        Next

        rootNode.ExpandAll()

    Catch xmlEx As XmlException
        MessageBox.Show(xmlEx.Message)
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try
End Sub

Public Sub addNode(xmlParent As XElement, node As TreeNode, parentNode As TreeNode)
    parentNode.Nodes.Add(node)

    For Each item In xmlParent.Elements()
        Dim chNode As New TreeNode(item.Name.LocalName)
        If item.NodeType = XmlNodeType.Element Then
            For Each attr In item.Attributes
                chNode.Nodes.Add(New TreeNode(attr.Name.ToString() + " = " + attr.Value))
            Next
        End If
        addNode(item, chNode, node)
    Next
End Sub
</code>```

Body:
I´m trying to populate a TreeView component in VB.NET from a XML file. It´s a large XML file and I chopped it up in order to give you guys an idea about how it is structured. I´m new to VB.NET so I´m having a hard time to figure this out. Below there´s an image of the order I expect this data to be shown in the TreeView, and I added some arrows so you can understand where the data is supposed to come from in the XML structure.

I found and tried to adapt a code I got from a Microsoft tutorial, but it´s based on a much simpler XML structure and it´s not working with my file.

The arrows in the image are being shown out of synch with the XML tags & nodes but my goal was to avoid the arrows and rectangles overlaping each other making the picture unreadable.

When we have a node named "Cutter" it´s a different type of component, and more than one may be comprised within the current "Cutter" or "Holder" node, so they are separated by the "Reference" tag. If it´s named "Holder" it´s another component type on the tool stackup... Every new tool starts with an element named "Tool".

Below the picture what I´m trying to do in the code:

Tree View Explanation

Private Sub btnSearchTLS_Click(sender As Object, e As EventArgs) Handles btnSearchTLS.Click

        Try
            ' SECTION 1. Create a DOM Document and load the XML data into it.
            Dim dom As New XmlDocument()
            dom.Load(txtFileOpenTLS_2.Text)

            ' SECTION 2. Initialize the treeview control.
            tviewToolIDs.Nodes.Clear()
            tviewToolIDs.Nodes.Add(New TreeNode(dom.DocumentElement.Name))
            Dim tNode As New TreeNode()
            tNode = tviewToolIDs.Nodes(0)

            ' SECTION 3. Populate the TreeView with the DOM nodes.
            AddNode(dom.DocumentElement, tNode)
            tviewToolIDs.ExpandAll()

        Catch xmlEx As XmlException
            MessageBox.Show(xmlEx.Message)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

    Private Sub AddNode(ByRef inXmlNode As XmlNode, ByRef inTreeNode As TreeNode)
        Dim xNode As XmlNode
        Dim tNode As TreeNode
        Dim nodeList As XmlNodeList
        Dim i As Integer

        ' Loop through the XML nodes until the leaf is reached.
        ' Add the nodes to the TreeView during the looping process.
        If inXmlNode.HasChildNodes() Then
            nodeList = inXmlNode.ChildNodes
            For i = 0 To nodeList.Count - 1
                xNode = inXmlNode.(i)
                inTreeNode.Nodes.Add(New TreeNode(xNode.Name))
                tNode = inTreeNode.Nodes(i)
                AddNode(xNode, tNode)
            Next
        Else
            ' Here you need to pull the data from the XmlNode based on the
            ' type of node, whether attribute values are required, and so forth.
            inTreeNode.Text = (inXmlNode.OuterXml).Trim
        End If
    End Sub

Here´s the XML file:

    <?xml version="1.0"?>
<ToolLibrary Version="7.3">
    <Tools>
    <Tool ID="100004" Units="Millimeter">
      <Description>100004</Description>
      <Teeth>1</Teeth>
      <Type>Turning</Type>
      <Cutter>
        <Reference ID="12140 - N123G2-0318-0008">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Torneamento - Insertos paramétricos</ToolID>
          <EntityName>12140 - N123G2-0318-0008</EntityName>
          <Origin>
            <X>34.2</X>
            <Y>0</Y>
            <Z>-82.3</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>-90</Y>
            <Z>0</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Cutter>
      <Holder>
        <Reference ID="12135 - C5-570-32-LF">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12135 - C5-570-32-LF</EntityName>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="12139 - 570-32L123G18B130A">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12139 - 570-32L123G18B130A</EntityName>
          <Origin>
            <X>21</X>
            <Y>0</Y>
            <Z>-42</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Holder>
      <DrivenPoint ID="1">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>35</X>
        <Y>0</Y>
        <Z>-83.1</Z>
      </DrivenPoint>
      <DrivenPoint ID="2">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>31.82</X>
        <Y>0</Y>
        <Z>-83.1</Z>
      </DrivenPoint>
      <CutterCompensation ID="1">0.8</CutterCompensation>
      <CutterCompensation ID="2">0.8</CutterCompensation>
    </Tool>
    <Tool ID="100171" Units="Millimeter">
      <Description>100171</Description>
      <Teeth>1</Teeth>
      <Type>Turning</Type>
      <Cutter>
        <Reference ID="12349 - CNMG120412">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Torneamento - Insertos paramétricos</ToolID>
          <EntityName>12349 - CNMG120412</EntityName>
          <Origin>
            <X>-35.8</X>
            <Y>0</Y>
            <Z>-291.8</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>-5</Y>
            <Z>0</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Cutter>
      <Holder>
        <Reference ID="11977 - C6-390.410-100-110A">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>11977 - C6-390.410-100-110A</EntityName>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="11978 - C6-570-2C-60-148-40L">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>11978 - C6-570-2C-60-148-40L</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-110</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="11979 - SL-PCLNL-40-12HP">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>11979 - SL-PCLNL-40-12HP</EntityName>
          <Origin>
            <X>-10</X>
            <Y>0</Y>
            <Z>-258</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Holder>
      <DrivenPoint ID="1">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>-37</X>
        <Y>0</Y>
        <Z>-293</Z>
      </DrivenPoint>
      <DrivenPoint ID="2">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>-37</X>
        <Y>0</Y>
        <Z>-293</Z>
      </DrivenPoint>
      <CutterCompensation ID="1">1.2</CutterCompensation>
      <CutterCompensation ID="2">1.2</CutterCompensation>
    </Tool>
    <Tool ID="100178" Units="Millimeter">
      <Description>100178</Description>
      <Teeth>8</Teeth>
      <Type>Milling</Type>
      <Cutter>
        <Reference ID="10084 - R90MT-12-05-RM">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>44</X>
            <Y>0</Y>
            <Z>-614</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM1">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>31.112698</X>
            <Y>-31.112698</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>-45</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM11">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>31.112698</X>
            <Y>31.112698</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>45</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM12">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>0</X>
            <Y>-44</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>-90</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM13">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>0</X>
            <Y>44</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>90</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM14">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>-31.112698</X>
            <Y>31.112698</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>135</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM15">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>-44</X>
            <Y>0</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>180</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10084 - R90MT-12-05-RM">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10084 - R90MT-12-05-RM</EntityName>
          <Origin>
            <X>-31.1127</X>
            <Y>-31.1127</Y>
            <Z>-614</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>-135</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Cutter>
      <Holder>
        <Reference ID="11974 - C8-390.410-100 120A">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>11974 - C8-390.410-100 120A</EntityName>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="12001 - C8-391.01-80 065">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12001 - C8-391.01-80 065</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-120</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="12001 - C8-391.01-80 065">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12001 - C8-391.01-80 065</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-185</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="12002 - C8-391.05-CD-32-320">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12002 - C8-391.05-CD-32-320</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-250</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10707 - FCM-D100-32-11">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>10707 - FCM-D100-32-11</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-570</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Holder>
      <DrivenPoint ID="1">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>0</X>
        <Y>0</Y>
        <Z>-620</Z>
      </DrivenPoint>
      <DrivenPoint ID="2">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>0</X>
        <Y>0</Y>
        <Z>-620</Z>
      </DrivenPoint>
      <CutterCompensation ID="1">50</CutterCompensation>
      <CutterCompensation ID="2">50</CutterCompensation>
    </Tool>
    <Tool ID="100192" Units="Millimeter">
      <Description>100192</Description>
      <Teeth>1</Teeth>
      <Type>Milling</Type>
      <Cutter>
        <Reference ID="10087 - 880-05-03-05H-C-GM">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10087 - 880-05-03-05H-C-GM</EntityName>
          <Origin>
            <X>-7.9</X>
            <Y>0</Y>
            <Z>-233.5</Z>
          </Origin>
          <Rotation>
            <X>0</X>
            <Y>0</Y>
            <Z>180</Z>
          </Rotation>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="10088 - 880-05 03 W05H-P-GM">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Rotativas - Insertos Paramétricos</ToolID>
          <EntityName>10088 - 880-05 03 W05H-P-GM</EntityName>
          <Origin>
            <X>12</X>
            <Y>0</Y>
            <Z>-233.5</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Cutter>
      <Holder>
        <Reference ID="12007 - C4-390.410-100-090A">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12007 - C4-390.410-100-090A</EntityName>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="12033 - 880-D2500C4-04">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12033 - 880-D2500C4-04</EntityName>
          <Origin>
            <X>0</X>
            <Y>0</Y>
            <Z>-90</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Holder>
      <DrivenPoint ID="1">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>0</X>
        <Y>0</Y>
        <Z>-234</Z>
      </DrivenPoint>
    </Tool>
    <Tool ID="801154" Units="Millimeter">
      <Description>801154</Description>
      <Teeth>1</Teeth>
      <Type>Turning</Type>
      <Cutter>
        <Reference ID="11325 - MKI-176807-13_4.4">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Torneamento - Insertos 3D</ToolID>
          <EntityName>11325 - MKI-176807-13_4.4</EntityName>
          <Origin>
            <X>-5.18</X>
            <Y>0</Y>
            <Z>-225</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Cutter>
      <Holder>
        <Reference ID="12016 - 392.410-100-ASHL-32">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>12016 - 392.410-100-ASHL-32</EntityName>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
        <Reference ID="11328 - MKS-366807-18">
          <FileName>TBT_MASTER_LIBRARY.tls</FileName>
          <ToolID>Holders & Acessorios</ToolID>
          <EntityName>11328 - MKS-366807-18</EntityName>
          <Origin>
            <X>-8</X>
            <Y>0</Y>
            <Z>-55</Z>
          </Origin>
          <NoSpin>0</NoSpin>
          <Alternate>Off</Alternate>
        </Reference>
      </Holder>
      <DrivenPoint ID="2">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>-2.980037</X>
        <Y>0</Y>
        <Z>-225</Z>
      </DrivenPoint>
      <DrivenPoint ID="1">
        <Type>-1</Type>
        <Radius>0</Radius>
        <X>-7.380037</X>
        <Y>0</Y>
        <Z>-225</Z>
      </DrivenPoint>
      <CutterCompensation ID="1">1.5</CutterCompensation>
      <CutterCompensation ID="2">1.5</CutterCompensation>
    </Tool>
  </Tools>
 </ToolLibrary>

What do I have to do in the code above (Considering it´s the right code - Feel free to come up with a new approach) to make my TreeView to be populated like shown in the image?

I´m sorry for asking for a thing possibly already covered, I did a search and could not find something that could work with my XML example.

Tks in advance,

Daniel

Body:
Use this.

Const FILENAME As String = "C:\joy\Web.config.xml"
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Try
            ' SECTION 1. Create a DOM Document and load the XML data into it

        Dim reader As New StreamReader(FILENAME, System.Text.Encoding.UTF8)
        Dim dom As XDocument = XDocument.Load(reader)            ' SECTION 2. Initialize the treeview control.
        Dim rootNode As New TreeNode(dom.Root.Name.LocalName)
        TreeView1.Nodes.Clear()
        TreeView1.Nodes.Add(rootNode)
        Dim ch = dom.Root.Elements()

        For Each obj As XElement In ch
            Dim chNode As New TreeNode(obj.Name.LocalName)
            addNode(obj, chNode, rootNode)
        Next

        rootNode.ExpandAll()

    Catch xmlEx As XmlException
        MessageBox.Show(xmlEx.Message)
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try
End Sub

Public Sub addNode(xmlParent As XElement, node As TreeNode, parentNode As TreeNode)
    parentNode.Nodes.Add(node)

    For Each item In xmlParent.Elements()
        Dim chNode As New TreeNode(item.Name.LocalName)
        If item.NodeType = XmlNodeType.Element Then
            For Each attr In item.Attributes
                chNode.Nodes.Add(New TreeNode(attr.Name.ToString() + " = " + attr.Value))
            Next
        End If
        addNode(item, chNode, node)
    Next
End Sub


来源: stackexchange

问:
display partial derivatives in maxima
I want to display the partial derivative df/dx of f(x,y) = ln(y-1-x^2)-xy^2.

A comparable example for what I want is:

```<code>(%i0) f(x) := x^8$
(%i1) diff(f(x),x);
(%o1) 8*x^7
</code>```

I've tried:

```<code>(%i1) f(x,y):=ln(y-1-x^2)-xy^2$

(%i2) g(x,y):=(diff(f(x,y), x));
(%o2) g(x,y):='diff(f(x,y),x,1)

(%i3) g(x,y):=''(diff(f(x,y), x));
(%o3) g(x,y):='diff(ln(y-x^2-1),x,1)
</code>```

But it doesn't work (the summand -xy^2 got deleted?).

I want the derivated function. Something like this:

```<code>             (2*x)
g(x,y):=  ——————————— - y^2
         (1 + x^2 - y)
</code>```

答:
the problem with your funciotn is that xy^2 instead of x*y^2for maxima is a variable you should write it as follows:</p>

```<code>(%i5) f(x,y):=ln(y-1-x^2)-x*y^2;

(\%o5) f\left(x , \linebreak[0]y\right):=\mathrm{ln}\left(y-1-x^2\right)-x\,y^2
(%i6) diff(f(x,y), x);

(\%o6) \ifracd{d}{d\,x}\,\mathrm{ln}\left(y-x^2-1\right)-y^2
</code>```

ContentLicense: CC BY-SA 3.0

Title: display partial derivatives in maxima

Body:
I want to display the partial derivative df/dx of f(x,y) = ln(y-1-x^2)-xy^2.

A comparable example for what I want is:

(%i0) f(x) := x^8$
(%i1) diff(f(x),x);
(%o1) 8*x^7

I've tried:

(%i1) f(x,y):=ln(y-1-x^2)-xy^2$

(%i2) g(x,y):=(diff(f(x,y), x));
(%o2) g(x,y):='diff(f(x,y),x,1)

(%i3) g(x,y):=''(diff(f(x,y), x));
(%o3) g(x,y):='diff(ln(y-x^2-1),x,1)

But it doesn't work (the summand -xy^2 got deleted?).

I want the derivated function. Something like this:

             (2*x)
g(x,y):=  ——————————— - y^2
         (1 + x^2 - y)

Body:
the problem with your funciotn is that xy^2 instead of x*y^2for maxima is a variable you should write it as follows:

(%i5) f(x,y):=ln(y-1-x^2)-x*y^2;

(\%o5) f\left(x , \linebreak[0]y\right):=\mathrm{ln}\left(y-1-x^2\right)-x\,y^2
(%i6) diff(f(x,y), x);

(\%o6) \ifracd{d}{d\,x}\,\mathrm{ln}\left(y-x^2-1\right)-y^2


问:
selenium wait for flash page load (document.ready)
I want to make screenshot on webpage which is written in flash

For that I have this code:

```<code>ChromeOptions options = new ChromeOptions();
IWebDriver driver = new ChromeDriver(options);
...
// I'm clicking on button whicch opens new browser window
driver.FindElement(By.ClassName("click_me")).Click();

Thread.Sleep(1500);
//switch to new window
driver.SwitchTo().Window(driver.WindowHandles.Last());

//maximize it
driver.Manage().Window.Maximize();

//wait for load
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);

//and then take screenshot
Screenshot sc = ((ITakesScreenshot)driver).GetScreenshot();

sc.SaveAsFile(String.Format(@"{0}\{1}.{2}", Environment.GetFolderPath(Environment.SpecialFolder.Desktop), Guid.NewGuid(), ScreenshotImageFormat.Png), ScreenshotImageFormat.Png);
</code>```

Here works everything but wait for load. It takes a screenshot of loading screen. What can i do?

答:
```<code>//wait for load
WaitForLoading(driver);

private void WaitForLoading(IWebDriver driver)
{
    var javascriptExecutor = (IJavaScriptExecutor)driver;
    _wait.Until(webDriver => javascriptExecutor.ExecuteScript("return document.readyState").ToString() == "complete");
}
</code>```

Body:
I want to make screenshot on webpage which is written in flash

For that I have this code:

ChromeOptions options = new ChromeOptions();
IWebDriver driver = new ChromeDriver(options);
...
// I'm clicking on button whicch opens new browser window
driver.FindElement(By.ClassName("click_me")).Click();

Thread.Sleep(1500);
//switch to new window
driver.SwitchTo().Window(driver.WindowHandles.Last());

//maximize it
driver.Manage().Window.Maximize();

//wait for load
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);

//and then take screenshot
Screenshot sc = ((ITakesScreenshot)driver).GetScreenshot();

sc.SaveAsFile(String.Format(@"{0}\{1}.{2}", Environment.GetFolderPath(Environment.SpecialFolder.Desktop), Guid.NewGuid(), ScreenshotImageFormat.Png), ScreenshotImageFormat.Png);

Here works everything but wait for load. It takes a screenshot of loading screen. What can i do?


问:
Jumping Scrollbar after auto-expanding textarea
I have an auto-expanding textarea.  When pasting extremely long text (longer than window height), subsequent typing causes the browser scrollbar to jump.  This happens when trying to type at the bottom, because the document height is also growing.

Ideas, anyone?

Codepen:  https://codepen.io/btn-ninja/pen/bRVKYe

```<code>function growTextarea (i,elem) {
    var elem = $(elem);
    var offset = elem.prop('offsetHeight') - elem.prop('clientHeight');
     var resizeTextarea = function( elem ) {
        elem.css('height', 'auto').css('height', elem.prop('scrollHeight') + offset );
    };
    elem.on('input', function() {
        resizeTextarea( $(this) );
    });
    resizeTextarea( $(elem) );
}

$('.jTextarea').each(growTextarea);
</code>```

答:
You could use $(window).scrollTop(elem.prop('scrollHeight')); to force the window to scroll to the bottom of the element.

function growTextarea (i,elem) {
  var elem = $(elem);
  var offset = elem.prop('offsetHeight') - elem.prop('clientHeight');
   var resizeTextarea = function( elem ) {
     elem.css('height', 'auto').css('height', elem.prop('scrollHeight') + offset );
     $(window).scrollTop(elem.prop('scrollHeight'));
  };
  elem.on('input', function() {
      resizeTextarea( $(this) );
  });
  resizeTextarea( $(elem) );
}

$('.jTextarea').each(growTextarea);```
<pre class="snippet-code-html lang-html prettyprint-override"><code><form style="width:500px; margin:20px auto;">
  <small>Known issue: When pasting extremely long text (longer than window height), subsequent typing causes the browser scrollbar to jump.</small><br>
  <textarea rows="1" class="jTextarea"></textarea>
</form></code>```

Body:
I have an auto-expanding textarea.  When pasting extremely long text (longer than window height), subsequent typing causes the browser scrollbar to jump.  This happens when trying to type at the bottom, because the document height is also growing.

Ideas, anyone?

Codepen:  https://codepen.io/btn-ninja/pen/bRVKYe

function growTextarea (i,elem) {
    var elem = $(elem);
    var offset = elem.prop('offsetHeight') - elem.prop('clientHeight');
     var resizeTextarea = function( elem ) {
        elem.css('height', 'auto').css('height', elem.prop('scrollHeight') + offset );
    };
    elem.on('input', function() {
        resizeTextarea( $(this) );
    });
    resizeTextarea( $(elem) );
}

$('.jTextarea').each(growTextarea);

Body:
You could use $(window).scrollTop(elem.prop('scrollHeight')); to force the window to scroll to the bottom of the element.

function growTextarea (i,elem) {
  var elem = $(elem);
  var offset = elem.prop('offsetHeight') - elem.prop('clientHeight');
   var resizeTextarea = function( elem ) {
     elem.css('height', 'auto').css('height', elem.prop('scrollHeight') + offset );
     $(window).scrollTop(elem.prop('scrollHeight'));
  };
  elem.on('input', function() {
      resizeTextarea( $(this) );
  });
  resizeTextarea( $(elem) );
}

$('.jTextarea').each(growTextarea);

<form style="width:500px; margin:20px auto;">
  <small>Known issue: When pasting extremely long text (longer than window height), subsequent typing causes the browser scrollbar to jump.</small><br>
  <textarea rows="1" class="jTextarea"></textarea>
</form>


问:
Trying to program two buttons to appear when the player in my game dies
I am writing to ask for some assistance please. I am trying to program two buttons a Main menu and Exit button in my game to appear only when my player dies. I have been trying to define the gameobject list with,

GameManager Script.

```<code>//Awake is always called before any Start functions
void Awake()
{
    //Check if instance already exists
    if (instance == null)

        //if not, set instance to this
        instance = this;

    //If instance already exists and it's not this:
    else if (instance != this)

        //Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
        Destroy(gameObject);

    //Sets this to not be destroyed when reloading scene
    DontDestroyOnLoad(gameObject);

    //Assign enemies to a new List of Enemy objects.
    enemies = new List<Enemy>();

    //Get a component reference to the attached BoardManager script
    boardScript = GetComponent<BoardManager>();

    //Call the InitGame function to initialize the first level
    //InitGame();
}

// TODO: Uncommented Code
/// <summary>
/// Called when the level / scene has finished loading
/// </summary>
/// <param name="scene"></param>
/// <param name="mode"></param>
void OnLevelFinishedLoading(Scene scene, LoadSceneMode mode)
{
    // Don't initialize game on main menu. That would be silly
    if (scene.buildIndex > 0)
    {
        InitGame();
    }

    level++; // Increment after we have loaded level. Might be a better place to put this
}

// TODO: Uncomemnted code
void OnEnable()
{
    SceneManager.sceneLoaded += OnLevelFinishedLoading;
}

void OnDisable()
{
    SceneManager.sceneLoaded -= OnLevelFinishedLoading;
}

//Initializes the game for each level.
void InitGame()
{
    //While doingSetup is true the player can't move, prevent player from moving while title card is up.
    doingSetup = true;

    //Get a reference to our image LevelImage by finding it by name.
    levelImage = GameObject.Find("LevelImage");

    //Get a reference to our text LevelText's text component by finding it by name and calling GetComponent.
    levelText = GameObject.Find("LevelText").GetComponent<Text>();

    //Set the text of levelText to the string "Day" and append the current level number.
    levelText.text = "Day " + level;

    //Set levelImage to active blocking player's view of the game board during setup.
    levelImage.SetActive(true);

    //Call the HideLevelImage function with a delay in seconds of levelStartDelay.
    Invoke("HideLevelImage", levelStartDelay);

    //Clear any Enemy objects in our List to prepare for next level.
    enemies.Clear();

    //Call the SetupScene function of the BoardManager script, pass it current level number.
    boardScript.SetupScene(level);

    // TODO: Removed initGame() from here. No need to call it twice
}

//Hides black image used between levels
void HideLevelImage()
{
    //Disable the levelImage gameObject.
    levelImage.SetActive(false);

    //Set doingSetup to false allowing player to move again.
    doingSetup = false;
}

//Update is called every frame.
void Update()
{
    //Check that playersTurn or enemiesMoving or doingSetup are not currently true.
    if (playersTurn || enemiesMoving || doingSetup)

        //If any of these are true, return and do not start MoveEnemies.
        return;

    //Start moving enemies.
    StartCoroutine(MoveEnemies());
}

//Call this to add the passed in Enemy to the List of Enemy objects.
public void AddEnemyToList(Enemy script)
{
    //Add Enemy to List enemies.
    enemies.Add(script);
}

public void ShowButtons()
{
    foreach (var Button in buttons)
    {
        var gameOver = GetComponent<Exit2>();
        Button.gameObject.SetActive(true);
    }
}

//GameOver is called when the player reaches 0 food points
public void GameOver()
{
    //Set levelText to display number of levels passed and game over message
    levelText.text = "After " + level + " days, you starved.";

    //Shows buttons on player's death.
    var gameOver = GetComponent<Exit2>();
    gameOver.ShowButtons("Main menu 2", "Exit2");

    //Enable black background image gameObject.
    levelImage.SetActive(true);

    //Disable this GameManager.
    enabled = false;
}

//Coroutine to move enemies in sequence.
IEnumerator MoveEnemies()
{
    //While enemiesMoving is true player is unable to move.
    enemiesMoving = true;

    //Wait for turnDelay seconds, defaults to .1 (100 ms).
    yield return new WaitForSeconds(turnDelay);

    //If there are no enemies spawned (IE in first level):
    if (enemies.Count == 0)
    {
        //Wait for turnDelay seconds between moves, replaces delay caused by enemies moving when there are none.
        yield return new WaitForSeconds(turnDelay);
    }

    //Loop through List of Enemy objects.
    for (int i = 0; i < enemies.Count; i++)
    {
        //Call the MoveEnemy function of Enemy at index i in the enemies List.
        enemies[i].MoveEnemy();

        //Wait for Enemy's moveTime before moving next Enemy,
        yield return new WaitForSeconds(enemies[i].moveTime);
    }
    //Once Enemies are done moving, set playersTurn to true so player can move.
    playersTurn = true;

    //Enemies are done moving, set enemiesMoving to false.
    enemiesMoving = false;
}

void Awake()
{
    // Get the buttons
    menuButtonList();
    //buttons = GetComponentsInChildren<Button>();

    // Disable them
    HideButtons();
}

public void HideButtons()
{
    foreach (var Button in buttons)
    {
        Button.gameObject.SetActive(false);
    }
}

public void LoadByIndex(int sceneIndex)
{
    SceneManager.LoadScene(sceneIndex);
}

public void Quit()
{
#if UNITY_EDITOR
    UnityEditor.EditorApplication.isPlaying = false;
#else
    Application.Quit();
#endif
}
</code>```

I just want to make it so in my GameManager script under GameOver function is called the two buttons appear with what s already defined in the game PLEASE CHECK the lines in GameManager 162-194 and all of Exit2.

答:
First of all you need a Canvas. Then you create the two buttons inside the canvas. Have a reference to the instance of this canvas in your GameManager script.

Deactivate it via .SetActive(false) when the game starts, then Activate it again when the GameOver happens via .SetActive(true).

Add 2 methods to the GameManager script, one for Exit and one for MainMenu. And have the two buttons you created have their OnClick event trigger those 2 methods.

Body:
I am writing to ask for some assistance please. I am trying to program two buttons a Main menu and Exit button in my game to appear only when my player dies. I have been trying to define the gameobject list with,

GameManager Script.

//Awake is always called before any Start functions
void Awake()
{
    //Check if instance already exists
    if (instance == null)

        //if not, set instance to this
        instance = this;

    //If instance already exists and it's not this:
    else if (instance != this)

        //Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
        Destroy(gameObject);

    //Sets this to not be destroyed when reloading scene
    DontDestroyOnLoad(gameObject);

    //Assign enemies to a new List of Enemy objects.
    enemies = new List<Enemy>();

    //Get a component reference to the attached BoardManager script
    boardScript = GetComponent<BoardManager>();

    //Call the InitGame function to initialize the first level
    //InitGame();
}

// TODO: Uncommented Code
///
/// Called when the level / scene has finished loading
///
/// <param name="scene"></param>
/// <param name="mode"></param>
void OnLevelFinishedLoading(Scene scene, LoadSceneMode mode)
{
    // Don't initialize game on main menu. That would be silly
    if (scene.buildIndex > 0)
    {
        InitGame();
    }

    level++; // Increment after we have loaded level. Might be a better place to put this
}

// TODO: Uncomemnted code
void OnEnable()
{
    SceneManager.sceneLoaded += OnLevelFinishedLoading;
}

void OnDisable()
{
    SceneManager.sceneLoaded -= OnLevelFinishedLoading;
}

//Initializes the game for each level.
void InitGame()
{
    //While doingSetup is true the player can't move, prevent player from moving while title card is up.
    doingSetup = true;

    //Get a reference to our image LevelImage by finding it by name.
    levelImage = GameObject.Find("LevelImage");

    //Get a reference to our text LevelText's text component by finding it by name and calling GetComponent.
    levelText = GameObject.Find("LevelText").GetComponent<Text>();

    //Set the text of levelText to the string "Day" and append the current level number.
    levelText.text = "Day " + level;

    //Set levelImage to active blocking player's view of the game board during setup.
    levelImage.SetActive(true);

    //Call the HideLevelImage function with a delay in seconds of levelStartDelay.
    Invoke("HideLevelImage", levelStartDelay);

    //Clear any Enemy objects in our List to prepare for next level.
    enemies.Clear();

    //Call the SetupScene function of the BoardManager script, pass it current level number.
    boardScript.SetupScene(level);

    // TODO: Removed initGame() from here. No need to call it twice
}

//Hides black image used between levels
void HideLevelImage()
{
    //Disable the levelImage gameObject.
    levelImage.SetActive(false);

    //Set doingSetup to false allowing player to move again.
    doingSetup = false;
}

//Update is called every frame.
void Update()
{
    //Check that playersTurn or enemiesMoving or doingSetup are not currently true.
    if (playersTurn || enemiesMoving || doingSetup)

        //If any of these are true, return and do not start MoveEnemies.
        return;

    //Start moving enemies.
    StartCoroutine(MoveEnemies());
}

//Call this to add the passed in Enemy to the List of Enemy objects.
public void AddEnemyToList(Enemy script)
{
    //Add Enemy to List enemies.
    enemies.Add(script);
}

public void ShowButtons()
{
    foreach (var Button in buttons)
    {
        var gameOver = GetComponent<Exit2>();
        Button.gameObject.SetActive(true);
    }
}

//GameOver is called when the player reaches 0 food points
public void GameOver()
{
    //Set levelText to display number of levels passed and game over message
    levelText.text = "After " + level + " days, you starved.";

    //Shows buttons on player's death.
    var gameOver = GetComponent<Exit2>();
    gameOver.ShowButtons("Main menu 2", "Exit2");

    //Enable black background image gameObject.
    levelImage.SetActive(true);

    //Disable this GameManager.
    enabled = false;
}

//Coroutine to move enemies in sequence.
IEnumerator MoveEnemies()
{
    //While enemiesMoving is true player is unable to move.
    enemiesMoving = true;

    //Wait for turnDelay seconds, defaults to .1 (100 ms).
    yield return new WaitForSeconds(turnDelay);

    //If there are no enemies spawned (IE in first level):
    if (enemies.Count == 0)
    {
        //Wait for turnDelay seconds between moves, replaces delay caused by enemies moving when there are none.
        yield return new WaitForSeconds(turnDelay);
    }

    //Loop through List of Enemy objects.
    for (int i = 0; i < enemies.Count; i++)
    {
        //Call the MoveEnemy function of Enemy at index i in the enemies List.
        enemies[i].MoveEnemy();

        //Wait for Enemy's moveTime before moving next Enemy,
        yield return new WaitForSeconds(enemies[i].moveTime);
    }
    //Once Enemies are done moving, set playersTurn to true so player can move.
    playersTurn = true;

    //Enemies are done moving, set enemiesMoving to false.
    enemiesMoving = false;
}

void Awake()
{
    // Get the buttons
    menuButtonList();
    //buttons = GetComponentsInChildren<Button>();

    // Disable them
    HideButtons();
}

public void HideButtons()
{
    foreach (var Button in buttons)
    {
        Button.gameObject.SetActive(false);
    }
}

public void LoadByIndex(int sceneIndex)
{
    SceneManager.LoadScene(sceneIndex);
}

public void Quit()
{
#if UNITY_EDITOR
    UnityEditor.EditorApplication.isPlaying = false;
#else
    Application.Quit();
#endif
}

I just want to make it so in my GameManager script under GameOver function is called the two buttons appear with what s already defined in the game PLEASE CHECK the lines in GameManager 162-194 and all of Exit2.


问:
Move textfield when keyboard appears swift
I'm using Swift for programing with iOS and I'm using this code to move the UITextField, but it does not work. I call the function keyboardWillShow correctly, but the textfield doesn't move. I'm using autolayout.

```<code>override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self);
}

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        //let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)

        var frame = self.ChatField.frame
        frame.origin.y = frame.origin.y - keyboardSize.height + 167
        self.chatField.frame = frame
        println("asdasd")
    }
}
</code>```

答:
If you are like me who has tried all the above solutions and still your problem is not solved, I have a got a great solution for you that works like a charm. First I want clarify few things about some of solutions mentioned above.

In my case IQkeyboardmanager was working only when there is no auto layout applied on the elements, if it is applied then IQkeyboard manager will not work the way we think.

Same thing with upward movement of self.view.

i have wriiten a objective c header with a swift support for pushing UITexfield upward when user clicks on it, solving the problem of keyboard covering the UITextfield : https://github.com/coolvasanth/smart_keyboard.

One who has An intermediate or higher level in iOS app development can easily understand the repository and implement it. All the best

Body:
I'm using Swift for programing with iOS and I'm using this code to move the UITextField, but it does not work. I call the function keyboardWillShow correctly, but the textfield doesn't move. I'm using autolayout.

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self);
}

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        //let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)

        var frame = self.ChatField.frame
        frame.origin.y = frame.origin.y - keyboardSize.height + 167
        self.chatField.frame = frame
        println("asdasd")
    }
}


问:
beautifulsoup unable to extract href link
So i am using selenium , phantomjs as my webdriver, and beautifulsoup.
currently i want to extract all the links which are underneath the attribute title.
The site i want to extract

However, it seems to be not picking up these links at all ! What is going on ?

```<code># The standard library modules
import os
import sys
import re

# The wget module
import wget

# The BeautifulSoup module
from bs4 import BeautifulSoup

# The selenium module
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

def getListLinks(link):
    #setup drivers
    driver = webdriver.PhantomJS(service_args=['--ignore-ssl-errors=true'])
    driver.get(link) # load the web page
    src = driver.page_source

    #Get text and split it
    soup = BeautifulSoup(src, 'html5lib')
    print soup
    links = soup.find_all('a')
    print links

    driver.close()

getListLinks("http://www.bursamalaysia.com/market/listed-companies/company-announcements/#/?category=FA&sub_category=FA1&alphabetical=All&company=9695&date_from=01/01/2012&date_to=31/12/2016")
</code>```

Here is an example of a link i want to extract

```<code><a href="/market/listed-companies/company-announcements/5455245">Quarterly rpt on consolidated results for the financial period ended 31/03/2017</a>
</code>```

答:
What I really don't understand is why you are mixing beautifullsoup with selenium. Selenium has it's own api for extract dom element. You don't need to bring BS4 into the picture. Besides BS4 can only work with static HTML and ignores dynamically generated HTML which your selenium instance is capable of handling.

Just do

```<code>driver.find_element_by_tag_name('a')
</code>```

Body:
So i am using selenium , phantomjs as my webdriver, and beautifulsoup.
currently i want to extract all the links which are underneath the attribute title.
The site i want to extract

However, it seems to be not picking up these links at all ! What is going on ?

# The standard library modules
import os
import sys
import re

# The wget module
import wget

# The BeautifulSoup module
from bs4 import BeautifulSoup

# The selenium module
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

def getListLinks(link):
    #setup drivers
    driver = webdriver.PhantomJS(service_args=['--ignore-ssl-errors=true'])
    driver.get(link) # load the web page
    src = driver.page_source

    #Get text and split it
    soup = BeautifulSoup(src, 'html5lib')
    print soup
    links = soup.find_all('a')
    print links

    driver.close()

getListLinks("http://www.bursamalaysia.com/market/listed-companies/company-announcements/#/?category=FA&sub_category=FA1&alphabetical=All&company=9695&date_from=01/01/2012&date_to=31/12/2016")

Here is an example of a link i want to extract

Quarterly rpt on consolidated results for the financial period ended 31/03/2017

Body:
What I really don't understand is why you are mixing beautifullsoup with selenium. Selenium has it's own api for extract dom element. You don't need to bring BS4 into the picture. Besides BS4 can only work with static HTML and ignores dynamically generated HTML which your selenium instance is capable of handling.

Just do

driver.find_element_by_tag_name('a')


问:
CouchDB timeout when requesting _session
I am using Angular 4 with PouchDB to get data from a CouchDB 2.0 installation. Furthermore I am using the pouchdb-authentication plugin to do the login and signup process.

The login and signup process is working perfectly.

The only thing where couchdb sends me a timeout is when I switch the route in angular (/product/:id) from /product/1 to /product/2 back and forth twice.
On every route change I am sending a request to get the session from couchdb (might not be very intelligent but it should still work) but after going back and forth couchdb sends me a timeout after 10 seconds. In this time I am also not able to access the couchdb interface.
I tried to send the http request on my own instead of using the plugin but that did not fix it.

This is my Auth Service:

```<code>export class AuthGuard implements CanActivate {
    public UserDB;

    constructor(
        private router: Router,
        public appState: AppState
    ) {
        this.UserDB = new PouchDB(this.appState.get('couchdburl') +
        '_users', {skipSetup: true});
    }

    public canActivate(route: ActivatedRouteSnapshot, state:
         RouterStateSnapshot) {
         return this.isLoggedIn();
    }

    public isLoggedIn() {
         return this.UserDB.getSession().then((response) => {
            if ( typeof response.userCtx !== typeof undefined && response.userCtx.name !== null ) {
                return true;
            } else {
                this.router.navigate(['/login']);
                return false;
            }
        }).catch((err) => {
            console.log(err);
        });
    }
</code>```

These are my routes:

```<code>export const ROUTES: Routes = [
  { path: '',      component: LoginComponent, pathMatch: 'full' },
  { path: 'login', component: LoginComponent},
  { path: '', component: MainComponent, children: [
    { path: 'home',  component: HomeComponent, canActivate: [AuthGuard] },
    { path: 'user-management',  component: UserManagementComponent,
    canActivate: [AuthGuard] },
    { path: 'product/:id',  component: ProjectComponent,
    canActivate: [AuthGuard] },
  ] },
  { path: '**',    component: NoContentComponent },
];
</code>```

答:
If you're using PouchDB live sync API in order to sync local and remote databases, it is possible that you forgot to cancel the live sync on user logout. You might check here to see how it's implemented.

If you're not using live sync, the issue might be due to PouchDB allDocs() options. Just set the timeout option equal to 0 and see if it can resolve the issue.

Body:
I am using Angular 4 with PouchDB to get data from a CouchDB 2.0 installation. Furthermore I am using the pouchdb-authentication plugin to do the login and signup process.

The login and signup process is working perfectly.

The only thing where couchdb sends me a timeout is when I switch the route in angular (/product/:id) from /product/1 to /product/2 back and forth twice.
On every route change I am sending a request to get the session from couchdb (might not be very intelligent but it should still work) but after going back and forth couchdb sends me a timeout after 10 seconds. In this time I am also not able to access the couchdb interface.
I tried to send the http request on my own instead of using the plugin but that did not fix it.

This is my Auth Service:

export class AuthGuard implements CanActivate {
    public UserDB;

    constructor(
        private router: Router,
        public appState: AppState
    ) {
        this.UserDB = new PouchDB(this.appState.get('couchdburl') +
        '_users', {skipSetup: true});
    }

    public canActivate(route: ActivatedRouteSnapshot, state:
         RouterStateSnapshot) {
         return this.isLoggedIn();
    }

    public isLoggedIn() {
         return this.UserDB.getSession().then((response) => {
            if ( typeof response.userCtx !== typeof undefined && response.userCtx.name !== null ) {
                return true;
            } else {
                this.router.navigate(['/login']);
                return false;
            }
        }).catch((err) => {
            console.log(err);
        });
    }

These are my routes:

export const ROUTES: Routes = [
  { path: '',      component: LoginComponent, pathMatch: 'full' },
  { path: 'login', component: LoginComponent},
  { path: '', component: MainComponent, children: [
    { path: 'home',  component: HomeComponent, canActivate: [AuthGuard] },
    { path: 'user-management',  component: UserManagementComponent,
    canActivate: [AuthGuard] },
    { path: 'product/:id',  component: ProjectComponent,
    canActivate: [AuthGuard] },
  ] },
  { path: '**',    component: NoContentComponent },
];


问:
Parser/split const char* in c++
I tried to find a solution but I did not find anything that solved my question.

I have a C++ program that receive a const char* variable (filedata) and the size (filesize). The contents of this variable is a csv format. Each field is separated by ';'. The content is also dynamic, and may have more or less content, since this variable represents a set of logs. There is also a delimiter \n to represent the line break.

Example 1 of filedata:

```<code>const char* filedata =
    "1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
    "1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68";
</code>```

Example 2 of fildedata:

```<code>const char* filedata =
    "1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
    "1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68\n"
    "1496843100;2017-06-07 13:45:00;000002DA;2800;0x23000CCD.VARIABLE69";
</code>```

If you see the example 1 only have 2 lines, and the example 2 have 3 lines. I never know how many lines I have. I can have 2, 3, 200, 1000, etc. lines and the filedata variable save all content.

So my objective is to receive this filedata variable (I also have access to filesize) and for each line I need to parse the field 1 and 2 (timestamp and the data in normal format).

Expected output (for the example 2):

```<code>1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
</code>```

In example 2 I have 3 lines, so I need to iterate all lines and for each line parse the specific fields, very similar to the output.
After this i pick each parser fields and save to object list (This part is already implemented. I'm just having trouble parsing filedata.

答:
Here is working code with the output you want. I used this SO answer to the SO question I reference to in my duplicate flag. I modified it, so that the new line character \n act also as delimiter. Therefore in the code are two while loops.

You have to pass the number of columns you want to have (cols) to the split() function. Also you can (optional) pass the columns that should be excluded (filtCol). The example under the code uses: cols = 5 and filtCols = (1 << 1) | (1 << 3), that means all five columns should be parsed except column 2 and 4. Thererfor just column 1, 3 and 5 are in the resulting vector. I used a bit pattern for it because it will evaluate faster than a list/array of numbers.

```<code>#include <string>
#include <sstream>
#include <vector>
#include <iterator>
#include <iostream>

template<typename Out>
void split(const std::string& s, char delim, size_t cols, size_t filtCol, Out result)
{
   std::stringstream ss;
   ss.str(s);
   std::string item;

   /* Two while loops two separate on new line first */
   while (std::getline(ss, item))
   {
      std::stringstream ssLine;
      ssLine.str(item);
      std::string itemLine;

      /* Parse line and separate */
      size_t curCol = 0;
      while (std::getline(ssLine, itemLine, delim))
      {
         /* Just add column is in range and is not excluded by */
         /* bit pattern!                                       */
         if (curCol < cols && (~filtCol & (1 << curCol)))
         {
            *(result++) = itemLine;
         }

         ++curCol;
      }
   }
}

std::vector<std::string> split(const std::string& s, char delim, size_t cols, size_t filtCol = 0)
{
   std::vector<std::string> elems;
   split(s, delim, cols, filtCol, std::back_inserter(elems));
   return elems;
}

/* Example usage */
int main()
{
   const char* filedataI =
       "1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
       "1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68\n"
       "1496843100;2017-06-07 13:45:00;000002DA;2800;0x23000CCD.VARIABLE69";

   size_t colsRange = 5; /* Parse from col 1 to 5 (all five) */
   size_t colsFiltered = (1 << 1) | (1 << 3); /* Exclude col 2 and 4 */
   size_t colsPerLine = 3; /* 5 - 2 = 3 */

   std::vector<std::string> strVecI = split(filedataI, ';', colsRange, colsFiltered);
   for (size_t idx = 0; idx < strVecI.size(); ++idx)
   {
      if (idx > 0 && 0 == idx % colsPerLine)
      {
         std::cout << std::endl;
      }
      std::cout << "\"" << strVecI[idx] << "\" " << " ";
   }
}
</code>```

Output with 3 columns wanted (5 with 2 excluded: cols = 5 and filtCols = (1 << 1) | (1 << 3)), I also printed additionally the " and three spaces in between:

```<code>"1496843100"  "000002D8"  "0x23000CCD.VARIABLE67"
"1496843100"  "000002D9"  "0x23000CCD.VARIABLE68"
"1496843100"  "000002DA"  "0x23000CCD.VARIABLE69"
</code>```

Title: Parser/split const char* in c++

Body:
I tried to find a solution but I did not find anything that solved my question.

I have a C++ program that receive a const char* variable (filedata) and the size (filesize). The contents of this variable is a csv format. Each field is separated by ';'. The content is also dynamic, and may have more or less content, since this variable represents a set of logs. There is also a delimiter \n to represent the line break.

Example 1 of filedata:

const char* filedata =
    "1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
    "1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68";

Example 2 of fildedata:

const char* filedata =
    "1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
    "1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68\n"
    "1496843100;2017-06-07 13:45:00;000002DA;2800;0x23000CCD.VARIABLE69";

If you see the example 1 only have 2 lines, and the example 2 have 3 lines. I never know how many lines I have. I can have 2, 3, 200, 1000, etc. lines and the filedata variable save all content.

So my objective is to receive this filedata variable (I also have access to filesize) and for each line I need to parse the field 1 and 2 (timestamp and the data in normal format).

Expected output (for the example 2):

1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00

In example 2 I have 3 lines, so I need to iterate all lines and for each line parse the specific fields, very similar to the output.
After this i pick each parser fields and save to object list (This part is already implemented. I'm just having trouble parsing filedata.

Body:
Here is working code with the output you want. I used this SO answer to the SO question I reference to in my duplicate flag. I modified it, so that the new line character \n act also as delimiter. Therefore in the code are two while loops.

You have to pass the number of columns you want to have (cols) to the split() function. Also you can (optional) pass the columns that should be excluded (filtCol). The example under the code uses: cols = 5 and filtCols = (1 << 1) | (1 << 3), that means all five columns should be parsed except column 2 and 4. Thererfor just column 1, 3 and 5 are in the resulting vector. I used a bit pattern for it because it will evaluate faster than a list/array of numbers.

#include <string>
#include <sstream>
#include <vector>
#include <iterator>
#include <iostream>

template<typename Out>
void split(const std::string& s, char delim, size_t cols, size_t filtCol, Out result)
{
   std::stringstream ss;
   ss.str(s);
   std::string item;

   /* Two while loops two separate on new line first */
   while (std::getline(ss, item))
   {
      std::stringstream ssLine;
      ssLine.str(item);
      std::string itemLine;

      /* Parse line and separate */
      size_t curCol = 0;
      while (std::getline(ssLine, itemLine, delim))
      {
         /* Just add column is in range and is not excluded by */
         /* bit pattern!                                       */
         if (curCol < cols && (~filtCol & (1 << curCol)))
         {
            *(result++) = itemLine;
         }

         ++curCol;
      }
   }
}

std::vector<std::string> split(const std::string& s, char delim, size_t cols, size_t filtCol = 0)
{
   std::vector<std::string> elems;
   split(s, delim, cols, filtCol, std::back_inserter(elems));
   return elems;
}

/* Example usage */
int main()
{
   const char* filedataI =
       "1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
       "1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68\n"
       "1496843100;2017-06-07 13:45:00;000002DA;2800;0x23000CCD.VARIABLE69";

   size_t colsRange = 5; /* Parse from col 1 to 5 (all five) */
   size_t colsFiltered = (1 << 1) | (1 << 3); /* Exclude col 2 and 4 */
   size_t colsPerLine = 3; /* 5 - 2 = 3 */

   std::vector<std::string> strVecI = split(filedataI, ';', colsRange, colsFiltered);
   for (size_t idx = 0; idx < strVecI.size(); ++idx)
   {
      if (idx > 0 && 0 == idx % colsPerLine)
      {
         std::cout << std::endl;
      }
      std::cout << "\"" << strVecI[idx] << "\" " << " ";
   }
}

Output with 3 columns wanted (5 with 2 excluded: cols = 5 and filtCols = (1 << 1) | (1 << 3)), I also printed additionally the " and three spaces in between:

"1496843100"  "000002D8"  "0x23000CCD.VARIABLE67"
"1496843100"  "000002D9"  "0x23000CCD.VARIABLE68"
"1496843100"  "000002DA"  "0x23000CCD.VARIABLE69"


问:
Group array of javascript objects based on value into there own sub array of objects
I have an array of Javascript objects like below.

```<code>        [{

            "email": "alex@test.com",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "40",
            "rate": "20",
            "amount": "200",
            "vat": "60",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "mike@test.com",
            "fn": "Mike",
            "sn": "Mann",
            "phone": "01233xxxxx",
            "hours": "50",
            "rate": "70",
            "amount": "500",
            "vat": "90",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "fred@test.com",
            "fn": "Fred",
            "sn": "Frogg",
            "phone": "01233xxxxx",
            "hours": "80",
            "rate": "90",
            "amount": "800",
            "vat": "100",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "alex@test.com",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "90",
            "rate": "30",
            "amount": "900",
            "vat": "120",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        }]
</code>```

What I ideally want is to group those of the same value (email) into there own sub array of objects i.e if you look at the array above you will see I have 2 entries for the same person Alex McPherson. What I want to do is the below if possible move and combine into a sub array and the same for any other value that exists more than once.

```<code>    [[{

        "email": "alex@test.com",
        "fn": "Alex",
        "sn": "McPherson",
        "phone": "01233xxxxx",
        "hours": "40",
        "rate": "20",
        "amount": "200",
        "vat": "60",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    },{

        "email": "alex@test.com",
        "fn": "Alex",
        "sn": "McPherson",
        "phone": "01233xxxxx",
        "hours": "90",
        "rate": "30",
        "amount": "900",
        "vat": "120",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    }],
    [{

        "email": "mike@test.com",
        "fn": "Mike",
        "sn": "Mann",
        "phone": "01233xxxxx",
        "hours": "50",
        "rate": "70",
        "amount": "500",
        "vat": "90",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    }],
    [{

        "email": "fred@test.com",
        "fn": "Fred",
        "sn": "Frogg",
        "phone": "01233xxxxx",
        "hours": "80",
        "rate": "90",
        "amount": "800",
        "vat": "100",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    }]]
</code>```

I can't seem to get my head around resorting the array.

答:
Here is working example. We use ES6 array .reduce() function.

      var data = [{

            "email": "alex@test.com",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "40",
            "rate": "20",
            "amount": "200",
            "vat": "60",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "mike@test.com",
            "fn": "Mike",
            "sn": "Mann",
            "phone": "01233xxxxx",
            "hours": "50",
            "rate": "70",
            "amount": "500",
            "vat": "90",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "fred@test.com",
            "fn": "Fred",
            "sn": "Frogg",
            "phone": "01233xxxxx",
            "hours": "80",
            "rate": "90",
            "amount": "800",
            "vat": "100",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "alex@test.com",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "90",
            "rate": "30",
            "amount": "900",
            "vat": "120",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        }]

        const grouped = data.reduce((previous, current) => {
          if (!previous[current.email]) {
            const found = previous.find(element => element.email === current.email);
            if (found) {
              const index = previous.indexOf(found);
              previous.splice(index,1);
              // We add always at the top
              previous.unshift([found, current]);
            } else {
              previous.push(current);
            }
          }

          return previous;
        }, [])

        console.log(grouped);
      ```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.as-console-wrapper { max-height: 100% !important; top: 0; }</code>```

Body:
I have an array of Javascript objects like below.

        [{

            "email": "alex@test.com",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "40",
            "rate": "20",
            "amount": "200",
            "vat": "60",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "mike@test.com",
            "fn": "Mike",
            "sn": "Mann",
            "phone": "01233xxxxx",
            "hours": "50",
            "rate": "70",
            "amount": "500",
            "vat": "90",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "fred@test.com",
            "fn": "Fred",
            "sn": "Frogg",
            "phone": "01233xxxxx",
            "hours": "80",
            "rate": "90",
            "amount": "800",
            "vat": "100",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "alex@test.com",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "90",
            "rate": "30",
            "amount": "900",
            "vat": "120",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        }]

What I ideally want is to group those of the same value (email) into there own sub array of objects i.e if you look at the array above you will see I have 2 entries for the same person Alex McPherson. What I want to do is the below if possible move and combine into a sub array and the same for any other value that exists more than once.

    [[{

        "email": "alex@test.com",
        "fn": "Alex",
        "sn": "McPherson",
        "phone": "01233xxxxx",
        "hours": "40",
        "rate": "20",
        "amount": "200",
        "vat": "60",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    },{

        "email": "alex@test.com",
        "fn": "Alex",
        "sn": "McPherson",
        "phone": "01233xxxxx",
        "hours": "90",
        "rate": "30",
        "amount": "900",
        "vat": "120",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    }],
    [{

        "email": "mike@test.com",
        "fn": "Mike",
        "sn": "Mann",
        "phone": "01233xxxxx",
        "hours": "50",
        "rate": "70",
        "amount": "500",
        "vat": "90",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    }],
    [{

        "email": "fred@test.com",
        "fn": "Fred",
        "sn": "Frogg",
        "phone": "01233xxxxx",
        "hours": "80",
        "rate": "90",
        "amount": "800",
        "vat": "100",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    }]]

I can't seem to get my head around resorting the array.

Body:
Here is working example. We use ES6 array .reduce() function.

      var data = [{

            "email": "alex@test.com",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "40",
            "rate": "20",
            "amount": "200",
            "vat": "60",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "mike@test.com",
            "fn": "Mike",
            "sn": "Mann",
            "phone": "01233xxxxx",
            "hours": "50",
            "rate": "70",
            "amount": "500",
            "vat": "90",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "fred@test.com",
            "fn": "Fred",
            "sn": "Frogg",
            "phone": "01233xxxxx",
            "hours": "80",
            "rate": "90",
            "amount": "800",
            "vat": "100",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "alex@test.com",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "90",
            "rate": "30",
            "amount": "900",
            "vat": "120",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        }]

        const grouped = data.reduce((previous, current) => {
          if (!previous[current.email]) {
            const found = previous.find(element => element.email === current.email);
            if (found) {
              const index = previous.indexOf(found);
              previous.splice(index,1);
              // We add always at the top
              previous.unshift([found, current]);
            } else {
              previous.push(current);
            }
          }

          return previous;
        }, [])

        console.log(grouped);

.as-console-wrapper { max-height: 100% !important; top: 0; }


问:
MySQL how to get first n groups?
For the follow table TestTable:

```<code>| Id | Name  | Flags |
|----|-------|-------|
| 1  | name1 |   1   |
| 2  | name2 |   1   |
| 3  | name3 |   2   |
| 4  | name4 |   2   |
| 5  | name5 |   3   |
</code>```

how to group by Flags and return the first 2 groups. That is to say I should return rows:

```<code>|  1    |  name1  |  1  |
|  2    |  name2  |  1  |
|  3    |  name3  |  2  |
|  4    |  name4  |  2  |
</code>```

I tried this:

```<code>select *
from TestTable
group by Flags
order by Flags
limit 0,2
</code>```

However the query returned 2 rows only.

答:
You could use a sub query to take only the first two flags, and join that:

```<code>select     t.id, t.name, t.flags
from       testtable t
inner join (select   distinct flags
            from     testtable
            order by 1
            limit    2) filter
        on filter.flags = t.flags;
</code>```

See it run on regtester.com

Title: MySQL how to get first n groups?

Body:
For the follow table TestTable:

| Id | Name  | Flags |
|----|-------|-------|
| 1  | name1 |   1   |
| 2  | name2 |   1   |
| 3  | name3 |   2   |
| 4  | name4 |   2   |
| 5  | name5 |   3   |

how to group by Flags and return the first 2 groups. That is to say I should return rows:

|  1    |  name1  |  1  |
|  2    |  name2  |  1  |
|  3    |  name3  |  2  |
|  4    |  name4  |  2  |

I tried this:

select *
from TestTable
group by Flags
order by Flags
limit 0,2

However the query returned 2 rows only.

Body:
You could use a sub query to take only the first two flags, and join that:

select     t.id, t.name, t.flags
from       testtable t
inner join (select   distinct flags
            from     testtable
            order by 1
            limit    2) filter
        on filter.flags = t.flags;

See it run on regtester.com


答:
Use <regex> library

and regex_token_iterator as splitter

First of all split with \n and with ;

the code:

```<code>const char* filedata =
    "1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
    "1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68\n"
    "1496843100;2017-06-07 13:45:00;000002DA;2800;0x23000CCD.VARIABLE69";

const char* begin_f = filedata;
const char* end___f = filedata + std::string( filedata ).size();

/* first of all split by newline */

std::vector< std::string > vec_str;
std::regex regex1( "\n" );
std::regex regex2( ";" );

std::regex_token_iterator< const char* > first( begin_f, end___f, regex1, -1 ), last;
vec_str.assign( first, last );

for( std::string str1 : vec_str ){

    /* then split by semicolon ; */
    std::regex_token_iterator< std::string::const_iterator > first( str1.begin(),str1.end(), regex2, -1 ), last;
    int counter = 2;
    while( first != last && counter-- ){
        std::cout << *first++ << " ";
    }
    std::cout << '\n';

}
</code>```

the output:

```<code>1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
</code>```

Title: Parser/split const char* in c++

Body:
Use <regex> library

and regex_token_iterator as splitter

First of all split with \n and with ;

the code:

const char* filedata =
    "1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
    "1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68\n"
    "1496843100;2017-06-07 13:45:00;000002DA;2800;0x23000CCD.VARIABLE69";

const char* begin_f = filedata;
const char* end___f = filedata + std::string( filedata ).size();

/* first of all split by newline */

std::vector< std::string > vec_str;
std::regex regex1( "\n" );
std::regex regex2( ";" );

std::regex_token_iterator< const char* > first( begin_f, end___f, regex1, -1 ), last;
vec_str.assign( first, last );

for( std::string str1 : vec_str ){

    /* then split by semicolon ; */
    std::regex_token_iterator< std::string::const_iterator > first( str1.begin(),str1.end(), regex2, -1 ), last;
    int counter = 2;
    while( first != last && counter-- ){
        std::cout << *first++ << " ";
    }
    std::cout << '\n';

}

the output:

1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00


问:
aclocal not found for mingw sh autogen.sh execution
i'm trying to execute

```<code>./autogen.sh
</code>```

script in cppunit folder from

http://www.freedesktop.org/wiki/Software/cppunit

but in a mingw shell(sh) i get next error:

```<code>error: aclocal not found
</code>```

aclocal m4 scripts are in

```<code>c:\MinGW\share\
</code>```

directory.

How to fix that error?

答:
Had a similar problem when compiling a libmodbus library (it uses the same build principle). I have entered the following commands in MSYS shell:

```<code>pacman -S msys/libtool

pacman -S msys/autoconf

pacman -S msys/automake-wrapper
</code>```

After that I was able to execute autogen.sh

Body:
i'm trying to execute

./autogen.sh

script in cppunit folder from

http://www.freedesktop.org/wiki/Software/cppunit

but in a mingw shell(sh) i get next error:

error: aclocal not found

aclocal m4 scripts are in

c:\MinGW\share\

directory.

How to fix that error?

Body:
Had a similar problem when compiling a libmodbus library (it uses the same build principle). I have entered the following commands in MSYS shell:

pacman -S msys/libtool

pacman -S msys/autoconf

pacman -S msys/automake-wrapper

After that I was able to execute autogen.sh


问:
sort the list of links by the name of the link
I have list of links

```<code>links = [
  '<a href="http://127.0.0.1:5000/project/24/portfolio/">Packaging Only Demo</a>',
  '<a href="http://127.0.0.1:5000/project/38/portfolio/">QA Source</a>',
  '<a href="http://127.0.0.1:5000/project/44/portfolio/">Complete Demo</a>'
]
</code>```

And I need to sort the list by the name of the link.

I tried to sort it with a regular expression but it lasted too long. The list consists of a multitude of references

```<code>import re
def sorted(x):
  return re.search(r'\>(.*)<', x).group(1)

links = sorted(links, key=sorted)
print(links)
</code>```

答:
One can use etree to parse the XML/HTML snippets and obtain the text between the  tags. Then you can use that to as a sorting criterion:

```<code><b>from lxml import etree</b>

result = sorted(links,<b>key=lambda x : etree.XML(x).text</b>)</code>```

So here we invoke the etree.XML(..) function to construct an element (the  tag), and with .text we obtain the text between the tags. We then thus can use this as the key of the sorting.

This results in:

```<code>>>> result
['<a href="http://127.0.0.1:5000/project/44/portfolio/">Complete Demo</a>', '<a href="http://127.0.0.1:5000/project/24/portfolio/">Packaging Only Demo</a>', '<a href="http://127.0.0.1:5000/project/38/portfolio/">QA Source</a>']
</code>```

Body:
I have list of links

links = [
  'Packaging Only Demo',
  'QA Source',
  'Complete Demo'
]

And I need to sort the list by the name of the link.

I tried to sort it with a regular expression but it lasted too long. The list consists of a multitude of references

import re
def sorted(x):
  return re.search(r'\>(.*)<', x).group(1)

links = sorted(links, key=sorted)
print(links)

Body:
One can use etree to parse the XML/HTML snippets and obtain the text between the <a> tags. Then you can use that to as a sorting criterion:

from lxml import etree

result = sorted(links,key=lambda x : etree.XML(x).text)

So here we invoke the etree.XML(..) function to construct an element (the <a> tag), and with .text we obtain the text between the tags. We then thus can use this as the key of the sorting.

This results in:

>>> result
['<a href="http://127.0.0.1:5000/project/44/portfolio/">Complete Demo</a>', '<a href="http://127.0.0.1:5000/project/24/portfolio/">Packaging Only Demo</a>', '<a href="http://127.0.0.1:5000/project/38/portfolio/">QA Source</a>']