来自C ++的MSXML-漂亮的打印/缩进新创建的文档
时间:2020-03-06 15:03:01 来源:igfitidea点击:
我正在使用MSXML解析器写出XML文件,并使用从此处下载的包装器:http://www.codeproject.com/KB/XML/JW_CXml.aspx。除了我从代码创建一个新文档(从而不从文件加载和修改)时,效果很好,而结果却大体相同。我希望元素缩进的很好,这样我就可以在文本编辑器中轻松阅读它。
谷歌搜索显示许多人在2001年左右提出了相同的问题。答复通常说"应用XSL转换"或者"添加自己的空白节点"。特别是最后一个让我走了%(因此,我希望在2008年,有一种更简单的方法来实现MSXML输出。所以我的问题是;在那里,我该如何使用它?
解决方案
除非该库具有format选项,否则唯一的其他方法是使用XSLT或者外部漂亮的打印机(我认为htmltidy也可以执行xml)
代码项目库中似乎没有选项,但是我们可以为MSXML指定XSLT样式表。
尝试一下,这是我几年前在网上发现的。
#include <msxml2.h> bool FormatDOMDocument (IXMLDOMDocument *pDoc, IStream *pStream) { // Create the writer CComPtr <IMXWriter> pMXWriter; if (FAILED (pMXWriter.CoCreateInstance(__uuidof (MXXMLWriter), NULL, CLSCTX_ALL))) { return false; } CComPtr <ISAXContentHandler> pISAXContentHandler; if (FAILED (pMXWriter.QueryInterface(&pISAXContentHandler))) { return false; } CComPtr <ISAXErrorHandler> pISAXErrorHandler; if (FAILED (pMXWriter.QueryInterface (&pISAXErrorHandler))) { return false; } CComPtr <ISAXDTDHandler> pISAXDTDHandler; if (FAILED (pMXWriter.QueryInterface (&pISAXDTDHandler))) { return false; } if (FAILED (pMXWriter ->put_omitXMLDeclaration (VARIANT_FALSE)) || FAILED (pMXWriter ->put_standalone (VARIANT_TRUE)) || FAILED (pMXWriter ->put_indent (VARIANT_TRUE)) || FAILED (pMXWriter ->put_encoding (L"UTF-8"))) { return false; } // Create the SAX reader CComPtr <ISAXXMLReader> pSAXReader; if (FAILED (pSAXReader.CoCreateInstance (__uuidof (SAXXMLReader), NULL, CLSCTX_ALL))) { return false; } if (FAILED (pSAXReader ->putContentHandler (pISAXContentHandler)) || FAILED (pSAXReader ->putDTDHandler (pISAXDTDHandler)) || FAILED (pSAXReader ->putErrorHandler (pISAXErrorHandler)) || FAILED (pSAXReader ->putProperty ( L"http://xml.org/sax/properties/lexical-handler", CComVariant (pMXWriter))) || FAILED (pSAXReader ->putProperty ( L"http://xml.org/sax/properties/declaration-handler", CComVariant (pMXWriter)))) { return false; } // Perform the write return SUCCEEDED (pMXWriter ->put_output (CComVariant (pStream))) && SUCCEEDED (pSAXReader ->parse (CComVariant (pDoc))); }
这是已接受答案的修改后的版本,它将在内存中转换(仅在最后几行中进行了更改,但是为了方便将来的读者,我将整个代码块发布出来):
bool CXml::FormatDOMDocument(IXMLDOMDocument *pDoc) { // Create the writer CComPtr <IMXWriter> pMXWriter; if (FAILED (pMXWriter.CoCreateInstance(__uuidof (MXXMLWriter), NULL, CLSCTX_ALL))) { return false; } CComPtr <ISAXContentHandler> pISAXContentHandler; if (FAILED (pMXWriter.QueryInterface(&pISAXContentHandler))) { return false; } CComPtr <ISAXErrorHandler> pISAXErrorHandler; if (FAILED (pMXWriter.QueryInterface (&pISAXErrorHandler))) { return false; } CComPtr <ISAXDTDHandler> pISAXDTDHandler; if (FAILED (pMXWriter.QueryInterface (&pISAXDTDHandler))) { return false; } if (FAILED (pMXWriter->put_omitXMLDeclaration (VARIANT_FALSE)) || FAILED (pMXWriter->put_standalone (VARIANT_TRUE)) || FAILED (pMXWriter->put_indent (VARIANT_TRUE)) || FAILED (pMXWriter->put_encoding (L"UTF-8"))) { return false; } // Create the SAX reader CComPtr <ISAXXMLReader> pSAXReader; if (FAILED(pSAXReader.CoCreateInstance(__uuidof (SAXXMLReader), NULL, CLSCTX_ALL))) { return false; } if (FAILED(pSAXReader->putContentHandler (pISAXContentHandler)) || FAILED(pSAXReader->putDTDHandler (pISAXDTDHandler)) || FAILED(pSAXReader->putErrorHandler (pISAXErrorHandler)) || FAILED(pSAXReader->putProperty (L"http://xml.org/sax/properties/lexical-handler", CComVariant (pMXWriter))) || FAILED(pSAXReader->putProperty (L"http://xml.org/sax/properties/declaration-handler", CComVariant (pMXWriter)))) { return false; } // Perform the write bool success1 = SUCCEEDED(pMXWriter->put_output(CComVariant(pDoc.GetInterfacePtr()))); bool success2 = SUCCEEDED(pSAXReader->parse(CComVariant(pDoc.GetInterfacePtr()))); return success1 && success2; }
我已经写了一个sed脚本,用于基本的xml缩进。如果其他所有方法都失败,则可以将其用作外部压头(将其保存到xmlindent.sed,然后使用sed -f xmlindent.sed <filename>处理xml)。我们可能需要cygwin或者其他posix环境才能使用它。
来源:
:a />/!N;s/\n/ /;ta s/ / /g;s/^ *//;s/ */ /g /^<!--/{ :e /-->/!N;s/\n//;te s/-->/\n/;D; } /^<[?!][^>]*>/{ H;x;s/\n//;s/>.*$/>/;p;bb } /^<\/[^>]*>/{ H;x;s/\n//;s/>.*$/>/;s/^ //;p;bb } /^<[^>]*\/>/{ H;x;s/\n//;s/>.*$/>/;p;bb } /^<[^>]*[^\/]>/{ H;x;s/\n//;s/>.*$/>/;p;s/^/ /;bb } /</!ba { H;x;s/\n//;s/ *<.*$//;p;s/[^ ].*$//;x;s/^[^<]*//;ba } :b { s/[^ ].*$//;x;s/^<[^>]*>//;ba }
糟糕,制表符似乎是乱码...我们可以从此处复制-浪费:sed(1)进行XML缩进