每个人-长期听众,第一次来电。
我一直在macOS 10.13上使用C中的libtidy。我从示例代码here开始,并修改它以读取本地html文件,而不是使用curl。一切都很好,除了文本。它会找到并输出我的测试文件中的每个标签,但似乎根本无法获取文本,这让我抓狂。
问题代码出现在DumpNode
树遍历函数中。我的hacked up版本:
#include <stdio.h>
#include <tidy.h>
#include <tidybuffio.h>
/* Wrapper functions for file i/o */
int w_getc(void* ptr)
{
return getc((FILE *)ptr);
}
void w_ungetc(void *ptr, unsigned char bv)
{
ungetc((int)bv, (FILE *)ptr);
}
Bool w_feof(void *ptr)
{
return (Bool)feof((FILE *)ptr);
}
/* Traverse the document tree */
void dumpNode(TidyDoc doc, TidyNode tnod, int indent)
{
TidyNode child;
for(child = tidyGetChild(tnod); child; child = tidyGetNext(child) ) {
ctmbstr name = tidyNodeGetName(child);
if (!name) {
/* if it doesn't have a name, then it's probably text, cdata, etc... */
TidyBuffer buf;
tidyBufInit(&buf);
if (tidyNodeHasText(doc, child) && tidyNodeGetText(doc, child, &buf)) {
printf("%u, %u, %u\n", buf.size, buf.allocated, buf.next);
printf("%*.*s\n", indent, indent, (buf.bp && buf.size > 0)?(char *)buf.bp:"");
}
tidyBufFree(&buf);
}
dumpNode(doc, child, indent + 4); /* recursive */
}
}
int main(int argc, char **argv)
{
if(argc == 2) {
TidyDoc tdoc;
int err;
FILE *fp;
TidyInputSource insrc;
tdoc = tidyCreate();
fp = fopen(argv[1], "r");
if (!fp) return -1;
if (tidyInitSource(&insrc, fp, &w_getc, &w_ungetc, &w_feof)) {
err = tidyParseSource(tdoc, &insrc); /* parse the input */
if(err >= 0) dumpNode(tdoc, tidyGetRoot(tdoc), 0); /* walk the tree */
}
/* clean-up */
fclose(fp);
tidyRelease(tdoc);
return err;
}
return 0;
}
我的编译器字符串:gcc -o TidyExample tidyexample.c -ltidy -DENABLE_DEBUG_LOG -DDEBUG_PPRINT -DDEBUG_INDENT
以下是我迄今为止的推断:
- 当遇到文本节点时,
tidyNodeHasText(doc, child);
和tidyNodeGetText(doc, child, &buf);
都返回yes
。 - 这告诉我
tidyNodeGetText
正在像它应该的那样调用漂亮的打印函数。我已经验证了TidyXmlOut
或TidyXhtmlOut
都没有为doc
设置,所以TY_(PPrintTree)
应该会触发。 - 由于我使用
-DENABLE_DEBUG_LOG
和-DDEBUG_PPRINT
,TY_(PPrintTree)
应该调用dbg_show_node
,但它似乎没有。这可能是因为node == NULL
条件提示立即返回,但我Assert了节点的存在,如果它不存在,tidyNodeGetText
将返回no
,所以这不可能发生。 - 我还尝试设置一个进度回调函数,以便更好地了解其中发生的情况,但奇怪的是,链接器无法识别符号
_tidySetPrettyPrinterCallback
。 - 埃塔:我发现了这个,还需要第二个链接库才能正常工作:
-ltidys
。我现在可以得到漂亮的打印机的进展。 - 上面的代码片段生成的唯一输出是第一个
printf
语句的0, 0, 0\n
和第二个语句的\n
。 - 顺便说一句,我剽窃的 curl 样本代码?它也有同样的问题。如果运行它,只要它遇到任何文本,就会得到一个segfault,因为它在调用
printf
之前不会检查缓冲区中是否有任何内容。
我没办法了。要么我做错了什么(可能),要么libtidy中有一个很大的bug(不太可能,但有可能)。
ETA:这里有一个很小的HTML文件,当你调用TidyExample minimal.html
时,通常会导致空缓冲区:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<p>This is text.</p>
</body>
</html>
2条答案
按热度按时间2ic8powd1#
好吧,我找到了一个“解决方案”。它完成了工作,但我不知道为什么。
所以,在发现
-ltidys
之后,我尝试设置漂亮的打印回调,我发现如果我设置一个,输出将是我所期望的。* 即使我实际上没有设置回调!*说真的,我所要做的就是插入
tidySetPrettyPrinterCallback(tdoc, NULL);
行,然后缓冲区就填满了,并像它们应该的那样打印出来。注解掉它,它就停止工作了。我研究了一些与
libtidys.a
相关的其他函数,它们似乎具有相同的效果。但我没有做过任何严格的实验。如果有人知道是什么导致了这一点,我很想知道,为了我自己的知识。但我不想再多问了。既然我已经找到了一个解决问题的实用方法,我就暂时不去管它了,而是去做我想使用Tidy的实际项目。
y3bcpkx12#
在macOS上,使用
-ltidy
,您将链接到动态的Tidy版本。使用... -o TidyExample tidyexample.c ./libtidy.a
编译以确保使用更新的静态库。