I have some poorly written xml that I'm trying to loop through and extract the test name, start, and end time of each test. I use that data to append a column to a csv. My current implementation checks every element in the xml and seems to be slow.
Here is a an xml example
/*virtual*/ uint32 HyOpenGL::AddTextureArray(uint32 uiNumColorChannels, uint32 uiWidth, uint32 uiHeight, vector<unsigned char *> &vPixelData)
{
GLenum eInternalFormat = uiNumColorChannels == 4 ? GL_RGBA8 : (uiNumColorChannels == 3 ? GL_RGB8 : GL_R8);
GLenum eFormat = uiNumColorChannels == 4 ? GL_RGBA : (uiNumColorChannels == 3 ? GL_RGB : GL_RED);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, eInternalFormat, uiWidth, uiHeight, static_cast<uint32>(vPixelData.size()), 0, eFormat, GL_UNSIGNED_BYTE, NULL);
GLuint hGLTextureArray;
glGenTextures(1, &hGLTextureArray);
//glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, hGLTextureArray);
// Create storage for the texture
glTexStorage3D(GL_TEXTURE_2D_ARRAY,
1, // Number of mipmaps
eInternalFormat, // Internal format
uiWidth, uiHeight, // width, height
static_cast<uint32>(vPixelData.size()));
for(unsigned int i = 0; i != vPixelData.size(); ++i)
{
// Write each texture into storage
glTexSubImage3D(GL_TEXTURE_2D_ARRAY,
0, // Mipmap number
0, 0, i, // xoffset, yoffset, zoffset
uiWidth, uiHeight, 1, // width, height, depth (of texture you're copying in)
eFormat, // format
GL_UNSIGNED_BYTE, // type
vPixelData[i]); // pointer to pixel data
GLenum eError = glGetError(); // Getting 'GL_INVALID_OPERATION' when > 1 texture depth. It's 'GL_NO_ERROR' otherwise
}
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return hGLTextureArray;
}
Trying to figure out how to get the Id value for the processStart that matches the name and options. So far I have:
<ProcessStart Id="1" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessStart Id="2" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessStart Id="3" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessEnd Id="1" Tick="7553"/>
<ProcessEnd Id="2" Tick="7553"/>
<ProcessEnd Id="3" Tick="7553"/>
<ProcessStart Id="17" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8126" />
<ProcessStart Id="18" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8127" />
<ProcessStart Id="19" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8127" />
<ProcessEnd Id="17" Tick="12873"/>
<ProcessEnd Id="18" Tick="12873"/>
<ProcessEnd Id="19" Tick="12873"/>
but rather than checking the last element that matches the test name it check the last element of the processStart. How do I address this? Or would the fastest way to extract this information be reading the input file line by line?
New Information I want to return the Id value where Id=3. This is the last value where all ProcessStarts with matching Name and Options exist. The current count shown immediately references the last instances of ProcessStart then checks the name and options conditions. I am looking for a way to find the last ProcessStart with matching conditions.
Perhaps a better example would be to match by options as name is the same for this instance so:
root.find('ProcessStart[@Name="%s"][last()]' % test_name).get('Id')
Using this example and this data set it will return an error 'NoneType' object has no attribute 'get' I believe this is because the last element doesnt match the options. However I'm trying to target the last ProcessStart with matching options.
COMPLETE CODE:
options=" /pi=5 /m=AA"
test_id=root.find('ProcessStart[@Options="%s"][last()]' % options).get('Id')
COMPLETE XML FILE:
import xml.etree.ElementTree as ET
#Read the xml file
tree = ET.parse('C:/Users/mkaminski/Desktop/sample.xml')
root = tree.getroot()
#get the first option
test_option=root.find('ProcessStart').get('Options')
test_id=root.find('ProcessStart[@Options="%s"][last()]' % test_option).get('Id')
ERROR:
<AppLog App="RPx" Version="0.6.1" BaseVer="0.0.1" Time="20160208153547" Tick="0">
<RPxTest TestName="Tests/WriteRead" LongName="WriteRead_b=0_pi=5_m=AA_i=0" Instances="16" Memory="49534849024" Options=" /pi=5 /m=AA" IdRange="1-17" Tick="1233" />
<ProcessStart Id="1" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessStart Id="2" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessStart Id="3" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessEnd Id="1" Tick="7553"/>
<ProcessEnd Id="2" Tick="7553"/>
<ProcessEnd Id="3" Tick="7553"/>
<RPxTest TestName="Tests/WriteRead" LongName="WriteRead_b=0_pi=25_m=AA_i=0" Instances="16" Memory="49534849024" Options=" /pi=25 /m=AA" IdRange="17-33" Tick="8126" />
<ProcessStart Id="17" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8126" />
<ProcessStart Id="18" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8127" />
<ProcessStart Id="19" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8127" />
<ProcessEnd Id="17" Tick="12873"/>
<ProcessEnd Id="18" Tick="12873"/>
<ProcessEnd Id="19" Tick="12873"/>
</AppLog>
答案 0 :(得分:3)
I think that you are running into a limitation in ElementTree's xpath support (which is not complete). Using lxml your command works perfectly.
To do this with ElementTree, retrieve all of the matching elements and let Python select the last one.
Change
.bss
color: resb 8
To
options=" /pi=5 /m=AA"
test_id=root.find('ProcessStart[@Options="%s"][last()]' % options).get('Id')
In this command, we get all matching ProcessStart elements (in order) as a list, and grab just the last one. Then we can grab the id.