Merged PR 2399218: using inbox NSXmlParser instead of xerces on ios/macos.
ios only supports a SAX parser. This change builds simple DOM like functionality on top of NSXmlParser. Got rid of ~2.7MB of xerces from the SDK binary. Current size is ~1.6MB. Can still use the xerces if needed using the -parser-xerces build flag. Default is to use inbox implementation. Verified tests pass on macos and ios. Related work items: #18565171
This commit is contained in:
Родитель
08c6b2cc0c
Коммит
5c3284d61c
|
@ -4,6 +4,8 @@ build=MinSizeRel
|
|||
arch=x86_64
|
||||
dataCompressionLib=libcompression
|
||||
bundle=off
|
||||
xmlparserLib=applexml
|
||||
xmlparser="-DXML_PARSER=applexml"
|
||||
|
||||
usage()
|
||||
{
|
||||
|
@ -12,6 +14,7 @@ usage()
|
|||
echo $'\t' "-arch OSX Architecture. Default x86_64 (simulator)"
|
||||
echo $'\t' "-xzlib Use MSIX SDK Zlib instead of inbox libCompression api. Default on iOS is libCompression."
|
||||
echo $'\t' "-sb Skip bundle support."
|
||||
echo $'\t' "-parser-xerces Use xerces xml parser instead of default apple xml parser."
|
||||
}
|
||||
|
||||
printsetup()
|
||||
|
@ -20,6 +23,7 @@ printsetup()
|
|||
echo "Architecture:" $arch
|
||||
echo "Data Compression library:" $dataCompressionLib
|
||||
echo "Skip bundle support:" $bundle
|
||||
echo "parser:" $xmlparserLib
|
||||
}
|
||||
|
||||
while [ "$1" != "" ]; do
|
||||
|
@ -33,6 +37,9 @@ while [ "$1" != "" ]; do
|
|||
-xzlib )dataCompressionLib=MSIX_SDK_zlib
|
||||
zlib="-DUSE_MSIX_SDK_ZLIB=on"
|
||||
;;
|
||||
-parser-xerces ) xmlparserLib=xerces
|
||||
xmlparser="-DXML_PARSER=xerces"
|
||||
;;
|
||||
-sb ) bundle="on"
|
||||
;;
|
||||
-h ) usage
|
||||
|
@ -51,5 +58,5 @@ cd .vs
|
|||
# clean up any old builds of msix modules
|
||||
find . -name *msix* -d | xargs rm -r
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=$build $zlib -DIOS=on -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.cmake -DCMAKE_OSX_ARCHITECTURES=$arch -DSKIP_BUNDLES=$bundle ..
|
||||
cmake -DCMAKE_BUILD_TYPE=$build $zlib -DIOS=on -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.cmake -DCMAKE_OSX_ARCHITECTURES=$arch $xmlparser -DSKIP_BUNDLES=$bundle ..
|
||||
make
|
||||
|
|
11
makemac.sh
11
makemac.sh
|
@ -3,13 +3,16 @@
|
|||
build=MinSizeRel
|
||||
dataCompressionLib=libcompression
|
||||
bundle=off
|
||||
xmlparserLib=applexml
|
||||
xmlparser="-DXML_PARSER=applexml"
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "usage: makemac [-b buildType] [-xzlib]"
|
||||
echo "usage: makemac [-b buildType] [-xzlib] [-parser-xerces]"
|
||||
echo $'\t' "-b Build type. Default MinSizeRel"
|
||||
echo $'\t' "-xzlib Use MSIX SDK Zlib instead of inbox libCompression api. Default on MacOS is libCompression."
|
||||
echo $'\t' "-sb Skip bundle support."
|
||||
echo $'\t' "-parser-xerces Use xerces xml parser instead of default apple xml parser."
|
||||
}
|
||||
|
||||
printsetup()
|
||||
|
@ -17,6 +20,7 @@ printsetup()
|
|||
echo "Build Type:" $build
|
||||
echo "Data Compression library:" $dataCompressionLib
|
||||
echo "Skip bundle support:" $bundle
|
||||
echo "parser:" $xmlparserLib
|
||||
}
|
||||
|
||||
while [ "$1" != "" ]; do
|
||||
|
@ -27,6 +31,9 @@ while [ "$1" != "" ]; do
|
|||
-xzlib )dataCompressionLib=MSIX_SDK_zlib
|
||||
zlib="-DUSE_MSIX_SDK_ZLIB=on"
|
||||
;;
|
||||
-parser-xerces ) xmlparserLib=xerces
|
||||
xmlparser="-DXML_PARSER=xerces"
|
||||
;;
|
||||
-sb ) bundle="on"
|
||||
;;
|
||||
-h ) usage
|
||||
|
@ -45,5 +52,5 @@ cd .vs
|
|||
# clean up any old builds of msix modules
|
||||
find . -name *msix* -d | xargs rm -r
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=$build $zlib -DSKIP_BUNDLES=$bundle -DMACOS=on ..
|
||||
cmake -DCMAKE_BUILD_TYPE=$build $zlib -DSKIP_BUNDLES=$bundle $xmlparser -DMACOS=on ..
|
||||
make
|
||||
|
|
|
@ -108,6 +108,11 @@ MIDL_DEFINE_GUID(IID, IID_IXercesElement, 0x07d6ee0e,0x2165,0x4b90,0x80,0x24,0x
|
|||
MIDL_DEFINE_GUID(IID, IID_IJavaXmlElement, 0x69ab3660,0x398d,0x4cd6,0xa1,0x31,0xe7,0x31,0x6,0x4,0xe,0x3b);
|
||||
#endif
|
||||
|
||||
#ifdef USING_APPLE_XML
|
||||
// {8FBC0096-E87D-406A-95D9-203ADEFBF9AF}
|
||||
MIDL_DEFINE_GUID(IID, IID_IAppleXmlElement, 0x8fbc0096, 0xe87d, 0x406a, 0x95, 0xd9, 0x20, 0x3a, 0xde, 0xfb, 0xf9, 0xaf);
|
||||
#endif
|
||||
|
||||
#ifdef USING_MSXML
|
||||
MIDL_DEFINE_GUID(IID, IID_IMSXMLElement, 0x2730f595,0x0c80,0x4f3e,0x88,0x91,0x75,0x3b,0x2e,0x8c,0x30,0x5d);
|
||||
MIDL_DEFINE_GUID(IID, IID_IMSXMLDom, 0xb6bca5f0,0xc6c1,0x4409,0x85,0xbe,0xe4,0x76,0xaa,0xbe,0xc1,0x9a);
|
||||
|
|
|
@ -22,6 +22,24 @@ if(XML_PARSER MATCHES javaxml)
|
|||
add_definitions(-DUSING_JAVAXML=1)
|
||||
endif()
|
||||
|
||||
if(XML_PARSER MATCHES applexml)
|
||||
message(STATUS "XML_PARSER defined. Using apple xml parser." )
|
||||
set(XmlParser)
|
||||
list(APPEND XmlParser
|
||||
"PAL/XML/APPLE/XmlObject.cpp"
|
||||
"PAL/XML/APPLE/NSXmlParserDelegateWrapper.mm"
|
||||
"PAL/XML/APPLE/NSXmlParserWrapper.mm"
|
||||
"PAL/XML/APPLE/XmlDocumentReader.cpp"
|
||||
)
|
||||
set(XmlParserHpp)
|
||||
list(APPEND XmlParserHpp
|
||||
"PAL/XML/APPLE/NSXmlParserDelegateWrapper.h"
|
||||
"PAL/XML/APPLE/NSXmlParserWrapper.h"
|
||||
"PAL/XML/APPLE/XmlDocumentReader.hpp"
|
||||
)
|
||||
add_definitions(-DUSING_APPLE_XML=1)
|
||||
endif()
|
||||
|
||||
if(XML_PARSER MATCHES msxml6)
|
||||
message(STATUS "XML_PARSER defined. Using MSXML6 XML parser." )
|
||||
set(XmlParser PAL/XML/msxml6/XmlObject.cpp)
|
||||
|
@ -102,8 +120,13 @@ else()
|
|||
# used to get the languages of the device
|
||||
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
|
||||
if(NOT COREFOUNDATION_LIBRARY)
|
||||
message(FATAL_ERROR "CoreFoundation not found")
|
||||
message(FATAL_ERROR "CoreFoundation library not found")
|
||||
endif()
|
||||
find_library(FOUNDATION_LIBRARY Foundation)
|
||||
if(NOT FOUNDATION_LIBRARY)
|
||||
message(FATAL_ERROR "Foundation library not found")
|
||||
endif()
|
||||
find_library (LIBSTDCXX NAMES stdc++)
|
||||
set(Applicability PAL/Applicability/Apple/Applicability.cpp)
|
||||
if(IOS)
|
||||
add_definitions(-DIOS)
|
||||
|
@ -226,6 +249,7 @@ set(LIB_PRIVATE_HEADERS
|
|||
../inc/ZipObject.hpp
|
||||
${InteropHpp}
|
||||
${BundleHeaders}
|
||||
${XmlParserHpp}
|
||||
)
|
||||
|
||||
set(LIB_SOURCES
|
||||
|
@ -369,7 +393,7 @@ if(AOSP)
|
|||
endif()
|
||||
|
||||
if((IOS) OR (MACOS))
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${COREFOUNDATION_LIBRARY})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${COREFOUNDATION_LIBRARY} ${FOUNDATION_LIBRARY} ${LIBSTDCXX})
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
|
|
|
@ -147,7 +147,8 @@ void CheckForJavaXmlParseException(JNIEnv* env)
|
|||
}
|
||||
else
|
||||
{
|
||||
ThrowError(MSIX::Error::XmlError);
|
||||
// We treat all other parser errors as fatal.
|
||||
ThrowError(MSIX::Error::XmlFatal);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,8 +203,7 @@ public:
|
|||
|
||||
bool ForEachElementIn(const ComPtr<IXmlElement>& root, XmlQueryName query, XmlVisitor& visitor) override
|
||||
{
|
||||
ComPtr<IJavaXmlElement> element;
|
||||
ThrowHrIfFailed(root->QueryInterface(UuidOfImpl<IJavaXmlElement>::iid, reinterpret_cast<void**>(&element)));
|
||||
ComPtr<IJavaXmlElement> element = root.As<IJavaXmlElement>();
|
||||
|
||||
std::unique_ptr<_jstring, JObjectDeleter> jquery(m_env->NewStringUTF(xPaths[static_cast<uint8_t>(query)]));
|
||||
std::unique_ptr<_jobjectArray, JObjectDeleter> javaElements(reinterpret_cast<jobjectArray>(m_env->CallObjectMethod(m_javaXmlDom.get(), getElementsFunc, element->GetJavaObject(), jquery.get())));
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// Copyright (C) 2017 Microsoft. All rights reserved.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSXmlParserDelegateWrapper : NSObject <NSXMLParserDelegate>
|
||||
-(id) initWithXmlDocumentReader:(void *) xmlDocumentReader;
|
||||
@end
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// Copyright (C) 2017 Microsoft. All rights reserved.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
#import "NSXmlParserDelegateWrapper.h"
|
||||
#import "XmlDocumentReader.hpp"
|
||||
|
||||
@implementation NSXmlParserDelegateWrapper{
|
||||
MSIX::XmlDocumentReader* m_xmlDocumentReader;
|
||||
}
|
||||
|
||||
- (id) initWithXmlDocumentReader:(void *)xmlDocumentReader{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
m_xmlDocumentReader = static_cast<MSIX::XmlDocumentReader*>(xmlDocumentReader);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) parserDidStartDocument:(NSXMLParser *)parser {
|
||||
}
|
||||
|
||||
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
|
||||
std::unique_ptr<MSIX::XmlNode> node(new MSIX::XmlNode());
|
||||
|
||||
node->NodeName = std::string([elementName UTF8String]);
|
||||
if (qName)
|
||||
{
|
||||
node->QualifiedNodeName = std::string([qName UTF8String]);
|
||||
}
|
||||
for(id key in attributeDict)
|
||||
{
|
||||
node->Attributes.emplace(std::string([key UTF8String]), std::string([[attributeDict objectForKey:key] UTF8String]));
|
||||
}
|
||||
m_xmlDocumentReader->ProcessNodeBegin(std::move(node));
|
||||
}
|
||||
|
||||
-(void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
|
||||
m_xmlDocumentReader->ProcessCharacters([string UTF8String]);
|
||||
}
|
||||
|
||||
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
|
||||
m_xmlDocumentReader->ProcessNodeEnd(std::string([elementName UTF8String]));
|
||||
}
|
||||
|
||||
- (void) parserDidEndDocument:(NSXMLParser *)parser {
|
||||
}
|
||||
|
||||
- (void) parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
|
||||
}
|
||||
@end
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// Copyright (C) 2017 Microsoft. All rights reserved.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace MSIX
|
||||
{
|
||||
class NSXmlParserWrapper
|
||||
{
|
||||
void* wrapped;
|
||||
public:
|
||||
NSXmlParserWrapper() = default;
|
||||
~NSXmlParserWrapper() = default;
|
||||
bool Parse(uint8_t * data, size_t length, void* xmlDocumentReader);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Copyright (C) 2017 Microsoft. All rights reserved.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
#import "NSXmlParserWrapper.h"
|
||||
#import "NSXmlParserDelegateWrapper.h"
|
||||
|
||||
namespace MSIX
|
||||
{
|
||||
bool NSXmlParserWrapper::Parse(uint8_t* data, size_t dataLength, void* xmlDocumentReader)
|
||||
{
|
||||
NSData *xmldata = [NSData dataWithBytes:data length:dataLength];
|
||||
wrapped = [[NSXMLParser alloc] initWithData:xmldata];
|
||||
|
||||
// Create an instance of our parser delegate and assign it to the parser
|
||||
NSXmlParserDelegateWrapper *parserDelegate = [[NSXmlParserDelegateWrapper alloc] initWithXmlDocumentReader:xmlDocumentReader];
|
||||
[(NSXMLParser*)wrapped setDelegate:parserDelegate];
|
||||
|
||||
return [(NSXMLParser*)wrapped parse];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
//
|
||||
// Copyright (C) 2017 Microsoft. All rights reserved.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
#include "XmlDocumentReader.hpp"
|
||||
#include "Exceptions.hpp"
|
||||
|
||||
namespace MSIX {
|
||||
|
||||
void XmlDocumentReader::Init()
|
||||
{
|
||||
m_wrapper = new NSXmlParserWrapper();
|
||||
}
|
||||
|
||||
bool XmlDocumentReader::Parse(uint8_t* data, size_t size)
|
||||
{
|
||||
return m_wrapper->Parse(data, size, this);
|
||||
}
|
||||
|
||||
void XmlDocumentReader::ProcessNodeBegin(std::unique_ptr<XmlNode> node)
|
||||
{
|
||||
if (m_currentNodeStack.empty())
|
||||
{
|
||||
m_currentNodeStack.push(node.get());
|
||||
m_root.swap(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto currentNode = m_currentNodeStack.top();
|
||||
m_currentNodeStack.push(node.get());
|
||||
currentNode->Children.emplace_back(std::move(node));
|
||||
}
|
||||
}
|
||||
|
||||
void XmlDocumentReader::ProcessNodeEnd(std::string nodeName)
|
||||
{
|
||||
if (!m_currentNodeStack.empty())
|
||||
{
|
||||
auto currentNode = m_currentNodeStack.top();
|
||||
ThrowErrorIf(Error::XmlFatal, nodeName.compare(currentNode->NodeName) != 0, "Node end does not match current node opened.");
|
||||
m_currentNodeStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void XmlDocumentReader::ProcessCharacters(std::string string)
|
||||
{
|
||||
auto currentNode = m_currentNodeStack.top();
|
||||
currentNode->Text.append(string);
|
||||
}
|
||||
|
||||
void XmlNode::FindElementsRecursive(std::string xpath, std::list<XmlNode*>& list)
|
||||
{
|
||||
size_t nextPathSeparatorIndex = xpath.find_first_of("//");
|
||||
std::string currentXpathSegment = xpath.substr(0, nextPathSeparatorIndex);
|
||||
|
||||
if (NodeName.compare(currentXpathSegment) == 0)
|
||||
{
|
||||
if (nextPathSeparatorIndex == std::string::npos)
|
||||
{
|
||||
list.emplace_back(this);
|
||||
}
|
||||
for(auto it = Children.begin(); it != Children.end(); ++it)
|
||||
{
|
||||
(*it)->FindElementsRecursive(xpath.substr(nextPathSeparatorIndex + 1), list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::list<XmlNode*> XmlNode::FindElements(std::string xpath)
|
||||
{
|
||||
std::list<XmlNode*> list;
|
||||
|
||||
if (xpath.size() >= 2 && xpath[0] == '.' && xpath[1] == '/')
|
||||
{
|
||||
std::string newXPath = xpath.substr(2);
|
||||
for(auto it = Children.begin(); it != Children.end(); ++it)
|
||||
{
|
||||
auto child = (*it).get();
|
||||
child->FindElementsRecursive(newXPath, list);
|
||||
}
|
||||
}
|
||||
else if (xpath.size() > 1 && xpath[0] == '/')
|
||||
{
|
||||
std::string newXPath = xpath.substr(1);
|
||||
FindElementsRecursive(newXPath, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// Copyright (C) 2017 Microsoft. All rights reserved.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
#pragma once
|
||||
#include "NSXmlParserWrapper.h"
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
|
||||
namespace MSIX {
|
||||
|
||||
class XmlAttribute
|
||||
{
|
||||
public:
|
||||
std::string Name;
|
||||
std::string Value;
|
||||
};
|
||||
|
||||
class XmlNode
|
||||
{
|
||||
public:
|
||||
std::map<std::string, std::string> Attributes;
|
||||
std::list<std::unique_ptr<XmlNode>> Children;
|
||||
std::string Text;
|
||||
std::string NodeName;
|
||||
std::string QualifiedNodeName;
|
||||
|
||||
std::list<XmlNode*> FindElements(std::string xpath);
|
||||
private:
|
||||
void FindElementsRecursive(std::string xpath, std::list<XmlNode*>& list);
|
||||
};
|
||||
|
||||
class XmlDocumentReader
|
||||
{
|
||||
public:
|
||||
void Init();
|
||||
|
||||
bool Parse(uint8_t* data, size_t size);
|
||||
|
||||
void ProcessNodeBegin(std::unique_ptr<XmlNode> node);
|
||||
void ProcessNodeEnd(std::string nodeName);
|
||||
void ProcessCharacters(std::string string);
|
||||
|
||||
XmlNode* GetRoot(){return m_root.get();};
|
||||
|
||||
private:
|
||||
NSXmlParserWrapper* m_wrapper;
|
||||
std::unique_ptr<XmlNode> m_root;
|
||||
std::stack<XmlNode*> m_currentNodeStack;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
//
|
||||
// Copyright (C) 2017 Microsoft. All rights reserved.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "Exceptions.hpp"
|
||||
#include "StreamBase.hpp"
|
||||
#include "IXml.hpp"
|
||||
#include "Encoding.hpp"
|
||||
#include "StreamHelper.hpp"
|
||||
#include "MSIXResource.hpp"
|
||||
#include "UnicodeConversion.hpp"
|
||||
#include "Enumerators.hpp"
|
||||
#include "XmlDocumentReader.hpp"
|
||||
|
||||
EXTERN_C const IID IID_IAppleXmlElement;
|
||||
|
||||
// An internal interface for apple XML document object model
|
||||
// {8FBC0096-E87D-406A-95D9-203ADEFBF9AF}
|
||||
interface IAppleXmlElement : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual MSIX::XmlNode* GetXmlNode() = 0;
|
||||
};
|
||||
|
||||
SpecializeUuidOfImpl(IAppleXmlElement);
|
||||
|
||||
namespace MSIX {
|
||||
|
||||
class XmlElement final : public ComClass<XmlElement, IXmlElement, IAppleXmlElement, IMsixElement>
|
||||
{
|
||||
public:
|
||||
XmlElement(IMsixFactory* factory, XmlNode* xmlNode) :
|
||||
m_factory(factory), m_xmlNode(xmlNode)
|
||||
{
|
||||
}
|
||||
|
||||
// IXmlElement
|
||||
std::string GetAttributeValue(XmlAttributeName attribute) override
|
||||
{
|
||||
auto intermediate = utf16_to_utf8(attributeNames[static_cast<uint8_t>(attribute)]);
|
||||
return GetAttributeValue(intermediate);
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> GetBase64DecodedAttributeValue(XmlAttributeName attribute) override
|
||||
{
|
||||
auto intermediate = GetAttributeValue(attribute);
|
||||
return GetBase64DecodedValue(intermediate);
|
||||
}
|
||||
|
||||
std::string GetText() override
|
||||
{
|
||||
return m_xmlNode->Text;
|
||||
}
|
||||
|
||||
// IAppleXmlElement
|
||||
XmlNode* GetXmlNode() override { return m_xmlNode; }
|
||||
|
||||
// IMsixElement
|
||||
HRESULT STDMETHODCALLTYPE GetAttributeValue(LPCWSTR name, LPWSTR* value) noexcept override try
|
||||
{
|
||||
ThrowErrorIf(Error::InvalidParameter, (value == nullptr), "bad pointer.");
|
||||
auto intermediate = utf16_to_utf8(name);
|
||||
auto attributeValue = GetAttributeValue(intermediate);
|
||||
return m_factory->MarshalOutString(attributeValue, value);;
|
||||
|
||||
} CATCH_RETURN();
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetText(LPWSTR* value) noexcept override try
|
||||
{
|
||||
ThrowErrorIf(Error::InvalidParameter, (value == nullptr), "bad pointer.");
|
||||
auto text = GetText();
|
||||
return m_factory->MarshalOutString(text, value);
|
||||
} CATCH_RETURN();
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetElements(LPCWSTR name, IMsixElementEnumerator** elements) noexcept override try
|
||||
{
|
||||
ThrowErrorIf(Error::InvalidParameter, (elements == nullptr || *elements != nullptr), "bad pointer.");
|
||||
|
||||
auto intermediate = utf16_to_utf8(name);
|
||||
|
||||
auto elementsFound = m_xmlNode->FindElements(intermediate);
|
||||
|
||||
std::vector<ComPtr<IMsixElement>> elementsEnum;
|
||||
for(auto element : elementsFound)
|
||||
{
|
||||
auto item = ComPtr<IMsixElement>::Make<XmlElement>(m_factory, element);
|
||||
elementsEnum.push_back(std::move(item));
|
||||
}
|
||||
|
||||
*elements = ComPtr<IMsixElementEnumerator>::
|
||||
Make<EnumeratorCom<IMsixElementEnumerator,IMsixElement>>(elementsEnum).Detach();
|
||||
|
||||
return static_cast<HRESULT>(Error::OK);
|
||||
} CATCH_RETURN();
|
||||
|
||||
private:
|
||||
IMsixFactory* m_factory = nullptr;
|
||||
XmlNode* m_xmlNode = nullptr;
|
||||
|
||||
std::string GetAttributeValue(std::string& attributeName)
|
||||
{
|
||||
return m_xmlNode->Attributes[attributeName];
|
||||
}
|
||||
};
|
||||
|
||||
class XmlDom final : public ComClass<XmlDom, IXmlDom>
|
||||
{
|
||||
public:
|
||||
XmlDom(IMsixFactory* factory, const ComPtr<IStream>& stream) :
|
||||
m_factory(factory), m_stream(stream)
|
||||
{
|
||||
auto buffer = Helper::CreateBufferFromStream(stream);
|
||||
|
||||
m_xmlDocumentReader.reset(new XmlDocumentReader());
|
||||
m_xmlDocumentReader->Init();
|
||||
ThrowErrorIfNot(MSIX::Error::XmlFatal, m_xmlDocumentReader->Parse(buffer.data(), buffer.size()), "Xml Parse failed.");
|
||||
|
||||
// Apple currently only supports SAX parser.
|
||||
// If schema validation is required, then use xerces as the xml parser.
|
||||
}
|
||||
|
||||
// IXmlDom
|
||||
MSIX::ComPtr<IXmlElement> GetDocument() override
|
||||
{
|
||||
return ComPtr<IXmlElement>::Make<XmlElement>(m_factory, m_xmlDocumentReader->GetRoot());
|
||||
}
|
||||
|
||||
bool ForEachElementIn(const ComPtr<IXmlElement>& root, XmlQueryName query, XmlVisitor& visitor) override
|
||||
{
|
||||
ComPtr<IAppleXmlElement> element = root.As<IAppleXmlElement>();
|
||||
XmlNode* xmlNode = element->GetXmlNode();
|
||||
auto elements = xmlNode->FindElements(xPaths[static_cast<uint8_t>(query)]);
|
||||
|
||||
for(auto element : elements)
|
||||
{
|
||||
auto item = ComPtr<IXmlElement>::Make<XmlElement>(m_factory, element);
|
||||
if (!visitor.Callback(visitor.context, item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
IMsixFactory* m_factory;
|
||||
ComPtr<IStream> m_stream;
|
||||
std::unique_ptr<XmlDocumentReader> m_xmlDocumentReader;
|
||||
};
|
||||
|
||||
class AppleXmlFactory final : public ComClass<AppleXmlFactory, IXmlFactory>
|
||||
{
|
||||
public:
|
||||
AppleXmlFactory(IMsixFactory* factory) : m_factory(factory)
|
||||
{
|
||||
}
|
||||
|
||||
ComPtr<IXmlDom> CreateDomFromStream(XmlContentType footPrintType, const ComPtr<IStream>& stream) override
|
||||
{
|
||||
return ComPtr<IXmlDom>::Make<XmlDom>(m_factory, stream);
|
||||
}
|
||||
protected:
|
||||
IMsixFactory* m_factory;
|
||||
};
|
||||
|
||||
ComPtr<IXmlFactory> CreateXmlFactory(IMsixFactory* factory) { return ComPtr<IXmlFactory>::Make<AppleXmlFactory>(factory); }
|
||||
|
||||
} // namespace MSIX
|
|
@ -363,8 +363,7 @@ public:
|
|||
|
||||
bool ForEachElementIn(const ComPtr<IXmlElement>& root, XmlQueryName query, XmlVisitor& visitor) override
|
||||
{
|
||||
ComPtr<IXercesElement> element;
|
||||
ThrowHrIfFailed(root->QueryInterface(UuidOfImpl<IXercesElement>::iid, reinterpret_cast<void**>(&element)));
|
||||
ComPtr<IXercesElement> element = root.As<IXercesElement>();
|
||||
|
||||
XercesXMLChPtr xPath(XMLString::transcode(xPaths[static_cast<uint8_t>(query)]));
|
||||
XercesPtr<DOMXPathResult> result(m_parser->getDocument()->evaluate(
|
||||
|
|
|
@ -7,14 +7,6 @@ project(apitest)
|
|||
# Define two variables in order not to repeat ourselves.
|
||||
set(BINARY_NAME apitest)
|
||||
|
||||
IF (XML_PARSER MATCHES xerces)
|
||||
add_definitions(-DUSING_XERCES=1)
|
||||
ENDIF()
|
||||
|
||||
if(XML_PARSER MATCHES javaxml)
|
||||
add_definitions(-DUSING_JAVAXML=1)
|
||||
endif()
|
||||
|
||||
IF (XML_PARSER MATCHES msxml6)
|
||||
add_definitions(-DUSING_MSXML=1)
|
||||
ENDIF()
|
||||
|
|
|
@ -12,10 +12,10 @@ static const char* packageToTest = "..\\test\\appx\\TestAppxPackage_Win32.appx";
|
|||
static const char* packageToTest = "../test/appx/TestAppxPackage_Win32.appx";
|
||||
#endif
|
||||
|
||||
#if defined(USING_XERCES) || defined (USING_JAVAXML)
|
||||
static const wchar_t* ApplicationXpath = L"/Package/Applications/Application";
|
||||
#else
|
||||
#if defined(USING_MSXML)
|
||||
static const wchar_t* ApplicationXpath = L"/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']";
|
||||
#else
|
||||
static const wchar_t* ApplicationXpath = L"/Package/Applications/Application";
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -84,10 +84,6 @@ static HRESULT RunTest(std::string packageName, std::string unpackFolder, MSIX_V
|
|||
if(expectedResult == result)
|
||||
{ std::cout << "Succeeded" << std::endl;
|
||||
}
|
||||
else if ((expectedResult == 4099) && (result == 4098))
|
||||
{
|
||||
std::cout << "Succeeded for AOSP JavaXml since it always returns 4098 for xml errors" << std::endl;
|
||||
}
|
||||
else
|
||||
{ std::cout << "Failed" << std::endl;
|
||||
g_TestFailed = true;
|
||||
|
|
Загрузка…
Ссылка в новой задаче