思路:
1分钟快速生成用于网页内容提取的xslt,具体内容如下
使用xml生成word的基本步骤在《使用xslt转化xml数据形成word文档导出.doc》中说明比较清楚了。但是其中的细节并未说到,因此自己折腾了两天总算成功了。以下是我在使用过程中碰到的问题要点:
1.使用xslt样式,这样可以很好的和xml结合,做出漂亮的报告
1、项目背景
1.下面通过例子演示:
简单 的xml以及对应的xml框架
2.分别创建03版本的word文档log_03.doc和o7版本的word文档log_07.docx,并都应用以上生成的log.xsd框架
分别另存为log_03_doc.xml,log_07_doc.xml。
3.
用log_03_doc.xml,log_07_doc.xml生成xslt文件log_03.xslt和log_07.xslt。
log_03_doc.xml生成log_03.xslt时会弹出以上对话框,仅仅选中xml中指定的namespace就可以了。
log_07_doc.xml生成log_07.xslt时会弹出以上对话框,就是没有xml中指定的namespace,所有无论怎么选,生成的xslt都不是我们想要的。
2.生成xml结构
在《Python即时网络爬虫项目说明》一文我们说过要做一个通用的网络爬虫,而且能节省程序员大半的时间,而焦点问题就是提取器使用的抓取规则需要快速生成。在python使用xslt提取网页数据一文,我们已经看到这个提取规则是xslt程序,在示例程序中,直接把一长段xslt赋值给变量,但是没有讲这一段xslt是怎么来的。
log_03_doc.xml生成log_03.xslt时会弹出以上对话框,不要随便再选其他namespace。
生成的xslt截图
如果再选中其他namespace,生成的xslt也不是我们要的。生成xslt截图
显然跟上面的不一样。
www.2979.com ,
网友必然会质疑:这个xslt这么长,编写不是要花很长时间?
要实现插入图片,需要修改log_03.doc.
重新生成log_03.xslt,并修改<ns0:image>节点。
1、删除整个v:shapetype 节点
2、删除
<w:binData节点中的数据,并添加<xsl:value-ofselect=”.”/>
修改之后
3、修改v:shape 节点,去掉 style 属性,增加xsl 节点,如下:
4、去掉w:pict 节点后面的带<xsl:value-ofselect=”.”/>的所有节点
例子中去掉了如下代码:
<w:r>
<w:t>
<xsl:value-of select=”.” />
</w:t>
</w:r>
如果没做第四步,则在word中会出现图片的二进制代码。
例子:
QDomDocumentdom;
QDomProcessingInstructionproc =
dom.createProcessingInstruction(
“xml”,
“version=”1.0″standalone=”no””
);
dom.appendChild(proc);
QDomElementr =dom.createElement(“log”);
dom.appendChild(r);
r.setAttribute(“xmlns”,”logs”);
QDomElementuserNode =dom.createElement(“user”);
r.appendChild(userNode);
QDomTextuserTextNode =dom.createTextNode(“john”);
userNode.appendChild(userTextNode);
QDomElementloginNode =dom.createElement(“login”);
r.appendChild(loginNode);
QDomTextloginTextNode =dom.createTextNode(“2015-01-1811:10:12”);
loginNode.appendChild(loginTextNode);
QDomElementlogoffNode =dom.createElement(“logoff”);
r.appendChild(logoffNode);
QDomTextlogoffTextNode =dom.createTextNode(“2015-01-1813:10:12”);
logoffNode.appendChild(logoffTextNode);
QDomElementimageNode =dom.createElement(“image”);
r.appendChild(imageNode);
QStringpng;
FILE*fpng =fopen(“2.jpg”,”rb”);
if( fpng )
{
encode(fpng,png,0 );
fclose(fpng );
}
imageNode.setAttribute(“style”,”width:300pt;height:300pt” );
charszBuffer[256];
//sprintf(szBuffer,”wordml://5.png”);
imageNode.setAttribute(“key”,”2.jpg” );
QDomTextlogonNodeTextNode =dom.createTextNode(png);
imageNode.appendChild(logonNodeTextNode);
QStringxml =dom.toString();
QFilefile(“log.xml”);
if(file.open(QIODevice::WriteOnly))
{
QTextStreamoutput( &file);
output.setCodec(QTextCodec::codecForName(“UTF-8”));
//QStringcontent = dom.toString();
output<< xml;
file.close();
}
QStringsrc =”msxsl.exe”;
QStringsrc1 =”log.xml”;
QStringsrc2 =”log_03.xslt”;
QStringsrc3 =QString(“122″)+”.doc”;
QProcess*proce =newQProcess( );
QStringListargumentList;
argumentList.append(src1 );
argumentList.append(src2 );
argumentList.append(“-o”);
argumentList.append(src3 );
proce->start(src, argumentList );
bool ret =proce->waitForStarted( 5000 );
xslt样式是个很有意思,也很强大的,现在用的很多,很方便就能做出一个漂亮的报告,可以百度一下,语法相当简单,跟写html差不多的.
实际情况是,这个xslt是通过GooSeeker的MS谋数台的直观标注功能自动生成的,熟练的话1分钟就搞定了。
在这里可以定制好,我们要生成报告,是什么样子的,然后在从xml获取数据.
2、MS谋数台能做什么
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<Head>
<style type="text/css">
body {
background:#fff;
margin:0;
padding:40px 20px;
font-family: "Arial", Arial, Sans-serif;
font-size: 16px;
color:#000;
}
table {
margin:5px 5px 0;
border:0px solid #222;
font-size: 0.8em;
}
td {
margin:5px 5px 0;
padding:10px 10px 10px 10px;
vertical-align:text-top;
border:1px solid #222;
border-width:1px 1px 1px 1px;
}
td.light {
border:0px solid #222;
}
td.number {
text-align:right;
}
td.status {
text-align:right;
vertical-align:text-bottom;
}
</style>
</Head>
<body>
<!--OVER RESULT -->
<xsl:variable name="OVER_STATUS" select="REPORT/OVER_STATUS"/>
<xsl:variable name="STATUS" select="REPORT/LOG_ENTRY/STATUS"/>
<h2>自动化测试执行报告</h2>
<!--table -->
<table border="1">
<!--all result value-->
<tr bgcolor="white" height = "35">
<td>Overall Test Result</td>
<td><xsl:value-of select="$OVER_STATUS"/></td>
<td colspan="2"> </td>
</tr>
<tr bgcolor="#D8BFD8" height = "35">
<th>执行时间</th>
<th>单步结果</th>
<th>响应CODE</th>
<th>Response信息</th>
</tr>
<!--select font color -->
<xsl:variable name="fontColor">
<xsl:choose>
<xsl:when test="$STATUS = FAILED or $STATUS = PASSED">
<xsl:text>white</xsl:text>
</xsl:when>
<xsl:otherwise>black</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!--background color-->
<xsl:variable name="backgroundColor">
<xsl:choose>
<xsl:when test="$STATUS = 'FAILED'">
<xsl:text>rgb(255,0,0)</xsl:text>
</xsl:when>
<xsl:when test="$STATUS = 'PASSED'">
<xsl:text>rgb(60,179,113)</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>white</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!--log entry-->
<xsl:for-each select = "REPORT/LOG_ENTRY">
<tr>
<td><xsl:value-of select="EXECUTION_TIME"/></td>
<td bgcolor="{$backgroundColor}"><xsl:value-of select="STEP_RESULT"/></td>
<td><xsl:value-of select="COMPONENT_NAME"/></td>
<td><xsl:value-of select="STEP_DESCRIPTION"/></td>
</tr>
</xsl:for-each>
<tr bgcolor="white">
<font color="{$fontColor}">
<td colspan="4">Overall Test Result:<xsl:value-of select="$OVER_STATUS"/></td>
</font>
</tr>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
MS谋数台有个图形化界面,把一系列html解析工具集成在一起,包括:
xml是要按照,xslt定制的结构进行生成,或者换句话说,xslt样式要按照xml结构去做
xml结构
MS谋数台界面分成三部分:DOM数窗口、内嵌浏览器窗口、工作台。在工作台上定义xslt转换规则。
REPORT/LOG_ENTRY
3、用MS谋数台生成XSLT
REPORT下OVER_STATUS节点,这个是整个报告的结果,只有当所有条目为passed时才会为passed
假设我们要抓取论坛帖子列表,下面一步步讲解操作方法:
第一步,打开GooSeeker的MS谋数台,输入要抓取的网址
第二步,在MS谋数台的浏览器显示窗口里,直接选取要提取的内容,并且起个名字,点击确认
每个LOG_ENTRY节点,代表一行数据
包括:
第三步,点击工作台的“测试”按钮,xslt就生成了,在“数据规则”窗口显示出来
STATUS单行数据执行状态
EXECUTION_TIME执行时间
通过以上的操作,不用编程,用图形化界面直接在页面上标注,1分钟就可以生成xslt
STEP_RESULT单步执行结果
4、怎样使用XSLT
COMPONENT_NAME组件名称,
在python使用xslt提取网页数据一文,我们把生成xslt作为一个字符串交给程序,给人感觉好像一下子回到了史前文明,前面讲的那么好,最后用了很原始的拷贝。其实不然,那个只是一个例子。在《python即时网络爬虫项目:
内容提取器的定义》一文已经初见端倪了,有多种注入xslt的方式,最自动化的方式是api,将在后续文章中详细讲解。
STEP_DESCRIPTION步骤描述
5、文档修改历史
2016-05-28:V3.0,增加第二章
2016-05-26:V2.0,增补文字说明
当然这些都可以自已定义,可以自己增加或减少,但是xslt表中也要相对应的增加或减少
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="LOG.XSLT" type="text/xsl"?>
<REPORT>
<OVER_STATUS>PASSED</OVER_STATUS>
<LOG_ENTRY>
<STATUS>FAILED</STATUS>
<EXECUTION_TIME>2017.06.15 15:57:16</EXECUTION_TIME>
<STEP_RESULT>FAILED</STEP_RESULT>
<COMPONENT_NAME>704</COMPONENT_NAME>
<STEP_DESCRIPTION>{u'nextUrl': u'http://www.elong.com', u'message': u'u9a8cu8bc1u7801u9519u8bef', u'code': u'704', u'success': False, u'isShowVerifyCode': True}</STEP_DESCRIPTION>
</LOG_ENTRY>
<LOG_ENTRY>
<STATUS>FAILED</STATUS>
<EXECUTION_TIME>2017.06.15 15:57:16</EXECUTION_TIME>
<STEP_RESULT>FAILED</STEP_RESULT>
<COMPONENT_NAME>704</COMPONENT_NAME>
<STEP_DESCRIPTION>{u'nextUrl': u'http://www.elong.com', u'message': u'u9a8cu8bc1u7801u9519u8bef', u'code': u'704', u'success': False, u'isShowVerifyCode': True}</STEP_DESCRIPTION>
</LOG_ENTRY>
</REPORT>
而焦点问题就是提取器使用的抓取规则需要快速生成,做出漂亮的报告。
下面上,生成xml的python代码,这个创建xml结构就很简单了.
使用xml.dom.minidom就可以了,掌握几个要点很容易就创建一个xml
1,创建一个xml文档
import xml.dom.minidom as xmlDoc #xmlDoc起的别名
xmldoc = xmlDoc.Document
2.因为我们要使用xslt样式,所以呢.
创建的xml第一行是xml头 <?xml version=”1.0″ encoding=”utf-8″?>
这样python默认已经有了,就不用我们创建了,那么
第二行,我们要写样式头 <?xml-stylesheet href=”LOG.XSLT”
type=”text/xsl”?> 头中写了引用相同目录下的LOG.XSLT ,类型TEXT/XSL
要注意一点href属性不要写成这样D:demoLOG.XSLT
这样写会有问题,只要把这个文件和xml放在同一目录就好了.
#xml样式
xlstNode = xmlD.createProcessingInstruction("xml-stylesheet","href="LOG.XSLT" type="text/xsl"")
xmlD.appendChild(xlstNode)
3.创建一个REPORT根节点,你也可以起名ROOT,叫什么名字看你自己了
创建节点用,createElement,之后用appendChild增加节点到xml对象
report = xmlD.createElement('REPORT')
xmlD.appendChild(report)
4.之后创建其它节点,一样用createElement,但是如果节点下要增加内容要用xmlDoc.createTextNode(‘passed’)
以下代码意思是:创建一个over_status的节点,节点文本为passed,然后,将此节点增加到根节点REPORT下
overStatus = xmlD.createElement('OVER_STATUS')
overStatus.appendChild(xmlD.createTextNode('PASSED'))
report.appendChild(overStatus)
有以上4点,基本创建一个xml没有问题了.
生成xml具体python代码:
以下代码创建根节点做为了一个单独的函数,之所以这么做因为要生成的报告,只创建一个根节点,和over_status
结果状态
其它累加的行放在了节点LOG_ENTRY下,一个根节点下可以有多个LOG_ENTRY节点……..一个LOG_ENTRY节点代码一行数据执行结果
#*_*coding:utf-8*_*
import xml.dom.minidom as xmlDoc
import os
import gl
import sys
class cREPORTXML(object):
def __init__(self):
self.__struct = self.createReportNode()
#创建report节点
def createReportNode(self):
try:
xmlD = xmlDoc.Document()
#xml样式
xlstNode = xmlD.createProcessingInstruction("xml-stylesheet","href="LOG.XSLT" type="text/xsl"")
xmlD.appendChild(xlstNode)
report = xmlD.createElement('REPORT')
xmlD.appendChild(report)
overStatus = xmlD.createElement('OVER_STATUS')
overStatus.appendChild(xmlD.createTextNode('PASSED'))
report.appendChild(overStatus)
returnResult = []
returnResult.append(xmlD)
returnResult.append(report)
except Exception,ex:
return ex.message
return returnResult
def writeReport(self,execTime,stepResult,comName,stepDisc):
#reportNodeList = self.createReportNode()
entry = self.createLogEntry(self.__struct[0],execTime,stepResult,comName,stepDisc)
self.__struct[1].appendChild(entry)
self.writeXml(self.__struct[0],gl.reporterPath+'reportxml.xml')
#self.writeXml(self.__struct[0],gl.reporterPath+'reportxml_%s.xml'%(gl.curTimeStr))
#-------------创建xml格式-有多个相同的节点,并且该节点下有4个名称相同的子节点----------------
def createLogEntry(self,docObj,executeTime,stepResult,componentName,stepDiscription):
entry = docObj.createElement("LOG_ENTRY")
status = docObj.createElement("STATUS")
nodeExecuteTime = docObj.createElement("EXECUTION_TIME")
nodeStepResult = docObj.createElement("STEP_RESULT")
nodeComponentName = docObj.createElement("COMPONENT_NAME")
nodeStepDiscription = docObj.createElement("STEP_DESCRIPTION")
status.appendChild(docObj.createTextNode(stepResult))
nodeExecuteTime.appendChild(docObj.createTextNode(executeTime))
nodeStepResult.appendChild(docObj.createTextNode(stepResult))
nodeComponentName.appendChild(docObj.createTextNode(componentName))
nodeStepDiscription.appendChild(docObj.createTextNode(stepDiscription))
entry.appendChild(status)
entry.appendChild(nodeExecuteTime)
entry.appendChild(nodeStepResult)
entry.appendChild(nodeComponentName)
entry.appendChild(nodeStepDiscription)
return entry
#参数,xml对象,准备存储xml文件路径,文件模式:读 and 写 (r and w)
def writeXml(self,xmlDoc,xmlPath):
f = open(xmlPath,"w")
xmlDoc.writexml(f,indent='t', addindent='t', newl='n', encoding="utf-8") #中间的加了一些格式符,这样生成的xml自动对齐格式
f.close()
if __name__=='__main__':
reportx =cREPORTXML()
print reportx.writeReport('20170602','PASSED','1-SETTEXT','AUTOMATION TEST')
print reportx.writeReport('20170606','FIELD','2-SETTEXT','AUTOMATION TEST')
用ie打开xml报告,当然可以看出总结果显示有点问题,这个不影响报告展示,代码中处理一下就好.
简单的报告就完成了,追求完美的可以在细化一下,增加一些其它信息,调整一下颜色.