diff options
Diffstat (limited to 'doc/examples')
-rw-r--r-- | doc/examples/Makefile.am | 55 | ||||
-rw-r--r-- | doc/examples/Makefile.in | 100 | ||||
-rw-r--r-- | doc/examples/examples.xml | 162 | ||||
-rw-r--r-- | doc/examples/examples.xsl | 5 | ||||
-rwxr-xr-x | doc/examples/index.py | 3 | ||||
-rw-r--r-- | doc/examples/io2.c | 45 | ||||
-rw-r--r-- | doc/examples/io2.res | 2 | ||||
-rw-r--r-- | doc/examples/parse3.c | 60 | ||||
-rw-r--r-- | doc/examples/parse4.c | 136 | ||||
-rw-r--r-- | doc/examples/tst.xml | 7 | ||||
-rw-r--r-- | doc/examples/xpath1.c | 1 | ||||
-rw-r--r-- | doc/examples/xpath1.res | 5 | ||||
-rw-r--r-- | doc/examples/xpath2.c | 189 | ||||
-rw-r--r-- | doc/examples/xpath2.res | 30 |
14 files changed, 746 insertions, 54 deletions
diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am index 754e663..0d4bf13 100644 --- a/doc/examples/Makefile.am +++ b/doc/examples/Makefile.am @@ -15,9 +15,9 @@ install-data-local: $(mkinstalldirs) $(DESTDIR)$(HTML_DIR) -@INSTALL@ -m 0644 $(srcdir)/*.html $(srcdir)/*.c $(srcdir)/*.xml $(srcdir)/*.xsl $(srcdir)/*.res $(DESTDIR)$(HTML_DIR) -EXTRA_DIST=examples.xsl index.py test1.xml examples.xml test2.xml writer.xml test3.xml reader1.res reader3.res tree1.res tree2.res io1.res +EXTRA_DIST=examples.xsl index.py test1.xml examples.xml test2.xml writer.xml test3.xml tst.xml reader1.res reader3.res tree1.res tree2.res io1.res io2.res xpath1.res xpath2.res -noinst_PROGRAMS=xpath1 parse1 parse2 tree1 tree2 testWriter reader1 reader2 reader3 io1 +noinst_PROGRAMS=xpath1 parse1 parse2 tree1 tree2 testWriter reader1 reader2 reader3 io1 parse3 parse4 io2 xpath2 xpath1_SOURCES=xpath1.c xpath1_LDFLAGS= @@ -69,25 +69,58 @@ io1_LDFLAGS= io1_DEPENDENCIES= $(DEPS) io1_LDADD= @RDL_LIBS@ $(LDADDS) +parse3_SOURCES=parse3.c +parse3_LDFLAGS= +parse3_DEPENDENCIES= $(DEPS) +parse3_LDADD= @RDL_LIBS@ $(LDADDS) + +parse4_SOURCES=parse4.c +parse4_LDFLAGS= +parse4_DEPENDENCIES= $(DEPS) +parse4_LDADD= @RDL_LIBS@ $(LDADDS) + +io2_SOURCES=io2.c +io2_LDFLAGS= +io2_DEPENDENCIES= $(DEPS) +io2_LDADD= @RDL_LIBS@ $(LDADDS) + +xpath2_SOURCES=xpath2.c +xpath2_LDFLAGS= +xpath2_DEPENDENCIES= $(DEPS) +xpath2_LDADD= @RDL_LIBS@ $(LDADDS) + +valgrind: + $(MAKE) CHECKER='valgrind -q' tests + tests: $(noinst_PROGRAMS) @(echo > .memdump) - @(./parse1 test1.xml) + @($(CHECKER) ././xpath1 test3.xml '//child2' > xpath1.tmp ; diff xpath1.tmp xpath1.res ; rm xpath1.tmp) + @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) + @($(CHECKER) ./parse1 test1.xml) + @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) + @($(CHECKER) ./parse2 test2.xml) + @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) + @($(CHECKER) ./tree1 test2.xml > tree1.tmp ; diff tree1.tmp tree1.res ; rm tree1.tmp) + @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) + @($(CHECKER) ./tree2 > tree2.tmp ; diff tree2.tmp tree2.res ; rm tree2.tmp) + @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) + @($(CHECKER) ./testWriter ; for i in 1 2 3 4 ; do diff writer.xml writer$$i.res ; done ; rm writer*.res) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./parse2 test2.xml) + @($(CHECKER) ./reader1 test2.xml > reader1.tmp ; diff reader1.tmp reader1.res ; rm reader1.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./tree1 test2.xml > tree1.tmp ; diff tree1.tmp tree1.res ; rm tree1.tmp) + @($(CHECKER) ./reader2 test2.xml > reader1.tmp ; diff reader1.tmp reader1.res ; rm reader1.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./tree2 > tree2.tmp ; diff tree2.tmp tree2.res ; rm tree2.tmp) + @($(CHECKER) ./reader3 > reader3.tmp ; diff reader3.tmp reader3.res ; rm reader3.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./testWriter ; for i in 1 2 3 4 ; do diff writer.xml writer$$i.res ; done ; rm writer*.res) + @($(CHECKER) ./io1 > io1.tmp ; diff io1.tmp io1.res ; rm -f io1.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./reader1 test2.xml > reader1.tmp ; diff reader1.tmp reader1.res ; rm reader1.tmp) + @($(CHECKER) ./parse3) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./reader2 test2.xml > reader1.tmp ; diff reader1.tmp reader1.res ; rm reader1.tmp) + @($(CHECKER) ./parse4 test3.xml) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./reader3 > reader3.tmp ; diff reader3.tmp reader3.res ; rm reader3.tmp) + @($(CHECKER) ./io2 > io2.tmp ; diff io2.tmp io2.res ; rm -f io2.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./io1 > io1.tmp ; diff io1.tmp io1.res ; rm -f io1.tmp) + @($(CHECKER) ./xpath2 test3.xml '//discarded' discarded > xpath2.tmp ; diff xpath2.tmp xpath2.res ; rm xpath2.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) diff --git a/doc/examples/Makefile.in b/doc/examples/Makefile.in index 7c1478f..237a07a 100644 --- a/doc/examples/Makefile.in +++ b/doc/examples/Makefile.in @@ -14,7 +14,7 @@ @SET_MAKE@ -SOURCES = $(io1_SOURCES) $(parse1_SOURCES) $(parse2_SOURCES) $(reader1_SOURCES) $(reader2_SOURCES) $(reader3_SOURCES) $(testWriter_SOURCES) $(tree1_SOURCES) $(tree2_SOURCES) $(xpath1_SOURCES) +SOURCES = $(io1_SOURCES) $(io2_SOURCES) $(parse1_SOURCES) $(parse2_SOURCES) $(parse3_SOURCES) $(parse4_SOURCES) $(reader1_SOURCES) $(reader2_SOURCES) $(reader3_SOURCES) $(testWriter_SOURCES) $(tree1_SOURCES) $(tree2_SOURCES) $(xpath1_SOURCES) $(xpath2_SOURCES) srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -40,7 +40,8 @@ host_triplet = @host@ noinst_PROGRAMS = xpath1$(EXEEXT) parse1$(EXEEXT) parse2$(EXEEXT) \ tree1$(EXEEXT) tree2$(EXEEXT) testWriter$(EXEEXT) \ reader1$(EXEEXT) reader2$(EXEEXT) reader3$(EXEEXT) \ - io1$(EXEEXT) + io1$(EXEEXT) parse3$(EXEEXT) parse4$(EXEEXT) io2$(EXEEXT) \ + xpath2$(EXEEXT) subdir = doc/examples DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -56,10 +57,16 @@ am_io1_OBJECTS = io1.$(OBJEXT) io1_OBJECTS = $(am_io1_OBJECTS) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = $(top_builddir)/libxml2.la $(am__DEPENDENCIES_1) +am_io2_OBJECTS = io2.$(OBJEXT) +io2_OBJECTS = $(am_io2_OBJECTS) am_parse1_OBJECTS = parse1.$(OBJEXT) parse1_OBJECTS = $(am_parse1_OBJECTS) am_parse2_OBJECTS = parse2.$(OBJEXT) parse2_OBJECTS = $(am_parse2_OBJECTS) +am_parse3_OBJECTS = parse3.$(OBJEXT) +parse3_OBJECTS = $(am_parse3_OBJECTS) +am_parse4_OBJECTS = parse4.$(OBJEXT) +parse4_OBJECTS = $(am_parse4_OBJECTS) am_reader1_OBJECTS = reader1.$(OBJEXT) reader1_OBJECTS = $(am_reader1_OBJECTS) am_reader2_OBJECTS = reader2.$(OBJEXT) @@ -74,14 +81,18 @@ am_tree2_OBJECTS = tree2.$(OBJEXT) tree2_OBJECTS = $(am_tree2_OBJECTS) am_xpath1_OBJECTS = xpath1.$(OBJEXT) xpath1_OBJECTS = $(am_xpath1_OBJECTS) +am_xpath2_OBJECTS = xpath2.$(OBJEXT) +xpath2_OBJECTS = $(am_xpath2_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/io1.Po ./$(DEPDIR)/parse1.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/parse2.Po ./$(DEPDIR)/reader1.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/reader2.Po ./$(DEPDIR)/reader3.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/testWriter.Po ./$(DEPDIR)/tree1.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/tree2.Po ./$(DEPDIR)/xpath1.Po +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/io1.Po ./$(DEPDIR)/io2.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/parse1.Po ./$(DEPDIR)/parse2.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/parse3.Po ./$(DEPDIR)/parse4.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/reader1.Po ./$(DEPDIR)/reader2.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/reader3.Po ./$(DEPDIR)/testWriter.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/tree1.Po ./$(DEPDIR)/tree2.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/xpath1.Po ./$(DEPDIR)/xpath2.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \ @@ -90,14 +101,16 @@ LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \ CCLD = $(CC) LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(io1_SOURCES) $(parse1_SOURCES) $(parse2_SOURCES) \ +SOURCES = $(io1_SOURCES) $(io2_SOURCES) $(parse1_SOURCES) \ + $(parse2_SOURCES) $(parse3_SOURCES) $(parse4_SOURCES) \ $(reader1_SOURCES) $(reader2_SOURCES) $(reader3_SOURCES) \ $(testWriter_SOURCES) $(tree1_SOURCES) $(tree2_SOURCES) \ - $(xpath1_SOURCES) -DIST_SOURCES = $(io1_SOURCES) $(parse1_SOURCES) $(parse2_SOURCES) \ + $(xpath1_SOURCES) $(xpath2_SOURCES) +DIST_SOURCES = $(io1_SOURCES) $(io2_SOURCES) $(parse1_SOURCES) \ + $(parse2_SOURCES) $(parse3_SOURCES) $(parse4_SOURCES) \ $(reader1_SOURCES) $(reader2_SOURCES) $(reader3_SOURCES) \ $(testWriter_SOURCES) $(tree1_SOURCES) $(tree2_SOURCES) \ - $(xpath1_SOURCES) + $(xpath1_SOURCES) $(xpath2_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -300,7 +313,7 @@ target_alias = @target_alias@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I@srcdir@/include @THREAD_CFLAGS@ @Z_CFLAGS@ DEPS = $(top_builddir)/libxml2.la LDADDS = @STATIC_BINARIES@ $(top_builddir)/libxml2.la @THREAD_LIBS@ @Z_LIBS@ $(ICONV_LIBS) -lm @WIN32_EXTRA_LIBADD@ -EXTRA_DIST = examples.xsl index.py test1.xml examples.xml test2.xml writer.xml test3.xml reader1.res reader3.res tree1.res tree2.res io1.res +EXTRA_DIST = examples.xsl index.py test1.xml examples.xml test2.xml writer.xml test3.xml tst.xml reader1.res reader3.res tree1.res tree2.res io1.res io2.res xpath1.res xpath2.res xpath1_SOURCES = xpath1.c xpath1_LDFLAGS = xpath1_DEPENDENCIES = $(DEPS) @@ -341,6 +354,22 @@ io1_SOURCES = io1.c io1_LDFLAGS = io1_DEPENDENCIES = $(DEPS) io1_LDADD = @RDL_LIBS@ $(LDADDS) +parse3_SOURCES = parse3.c +parse3_LDFLAGS = +parse3_DEPENDENCIES = $(DEPS) +parse3_LDADD = @RDL_LIBS@ $(LDADDS) +parse4_SOURCES = parse4.c +parse4_LDFLAGS = +parse4_DEPENDENCIES = $(DEPS) +parse4_LDADD = @RDL_LIBS@ $(LDADDS) +io2_SOURCES = io2.c +io2_LDFLAGS = +io2_DEPENDENCIES = $(DEPS) +io2_LDADD = @RDL_LIBS@ $(LDADDS) +xpath2_SOURCES = xpath2.c +xpath2_LDFLAGS = +xpath2_DEPENDENCIES = $(DEPS) +xpath2_LDADD = @RDL_LIBS@ $(LDADDS) all: all-am .SUFFIXES: @@ -384,12 +413,21 @@ clean-noinstPROGRAMS: io1$(EXEEXT): $(io1_OBJECTS) $(io1_DEPENDENCIES) @rm -f io1$(EXEEXT) $(LINK) $(io1_LDFLAGS) $(io1_OBJECTS) $(io1_LDADD) $(LIBS) +io2$(EXEEXT): $(io2_OBJECTS) $(io2_DEPENDENCIES) + @rm -f io2$(EXEEXT) + $(LINK) $(io2_LDFLAGS) $(io2_OBJECTS) $(io2_LDADD) $(LIBS) parse1$(EXEEXT): $(parse1_OBJECTS) $(parse1_DEPENDENCIES) @rm -f parse1$(EXEEXT) $(LINK) $(parse1_LDFLAGS) $(parse1_OBJECTS) $(parse1_LDADD) $(LIBS) parse2$(EXEEXT): $(parse2_OBJECTS) $(parse2_DEPENDENCIES) @rm -f parse2$(EXEEXT) $(LINK) $(parse2_LDFLAGS) $(parse2_OBJECTS) $(parse2_LDADD) $(LIBS) +parse3$(EXEEXT): $(parse3_OBJECTS) $(parse3_DEPENDENCIES) + @rm -f parse3$(EXEEXT) + $(LINK) $(parse3_LDFLAGS) $(parse3_OBJECTS) $(parse3_LDADD) $(LIBS) +parse4$(EXEEXT): $(parse4_OBJECTS) $(parse4_DEPENDENCIES) + @rm -f parse4$(EXEEXT) + $(LINK) $(parse4_LDFLAGS) $(parse4_OBJECTS) $(parse4_LDADD) $(LIBS) reader1$(EXEEXT): $(reader1_OBJECTS) $(reader1_DEPENDENCIES) @rm -f reader1$(EXEEXT) $(LINK) $(reader1_LDFLAGS) $(reader1_OBJECTS) $(reader1_LDADD) $(LIBS) @@ -411,6 +449,9 @@ tree2$(EXEEXT): $(tree2_OBJECTS) $(tree2_DEPENDENCIES) xpath1$(EXEEXT): $(xpath1_OBJECTS) $(xpath1_DEPENDENCIES) @rm -f xpath1$(EXEEXT) $(LINK) $(xpath1_LDFLAGS) $(xpath1_OBJECTS) $(xpath1_LDADD) $(LIBS) +xpath2$(EXEEXT): $(xpath2_OBJECTS) $(xpath2_DEPENDENCIES) + @rm -f xpath2$(EXEEXT) + $(LINK) $(xpath2_LDFLAGS) $(xpath2_OBJECTS) $(xpath2_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -419,8 +460,11 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse3.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse4.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reader1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reader2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reader3.Po@am__quote@ @@ -428,6 +472,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tree1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tree2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xpath1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xpath2.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @@ -640,25 +685,38 @@ install-data-local: $(mkinstalldirs) $(DESTDIR)$(HTML_DIR) -@INSTALL@ -m 0644 $(srcdir)/*.html $(srcdir)/*.c $(srcdir)/*.xml $(srcdir)/*.xsl $(srcdir)/*.res $(DESTDIR)$(HTML_DIR) +valgrind: + $(MAKE) CHECKER='valgrind -q' tests + tests: $(noinst_PROGRAMS) @(echo > .memdump) - @(./parse1 test1.xml) + @($(CHECKER) ././xpath1 test3.xml '//child2' > xpath1.tmp ; diff xpath1.tmp xpath1.res ; rm xpath1.tmp) + @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) + @($(CHECKER) ./parse1 test1.xml) + @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) + @($(CHECKER) ./parse2 test2.xml) + @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) + @($(CHECKER) ./tree1 test2.xml > tree1.tmp ; diff tree1.tmp tree1.res ; rm tree1.tmp) + @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) + @($(CHECKER) ./tree2 > tree2.tmp ; diff tree2.tmp tree2.res ; rm tree2.tmp) + @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) + @($(CHECKER) ./testWriter ; for i in 1 2 3 4 ; do diff writer.xml writer$$i.res ; done ; rm writer*.res) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./parse2 test2.xml) + @($(CHECKER) ./reader1 test2.xml > reader1.tmp ; diff reader1.tmp reader1.res ; rm reader1.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./tree1 test2.xml > tree1.tmp ; diff tree1.tmp tree1.res ; rm tree1.tmp) + @($(CHECKER) ./reader2 test2.xml > reader1.tmp ; diff reader1.tmp reader1.res ; rm reader1.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./tree2 > tree2.tmp ; diff tree2.tmp tree2.res ; rm tree2.tmp) + @($(CHECKER) ./reader3 > reader3.tmp ; diff reader3.tmp reader3.res ; rm reader3.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./testWriter ; for i in 1 2 3 4 ; do diff writer.xml writer$$i.res ; done ; rm writer*.res) + @($(CHECKER) ./io1 > io1.tmp ; diff io1.tmp io1.res ; rm -f io1.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./reader1 test2.xml > reader1.tmp ; diff reader1.tmp reader1.res ; rm reader1.tmp) + @($(CHECKER) ./parse3) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./reader2 test2.xml > reader1.tmp ; diff reader1.tmp reader1.res ; rm reader1.tmp) + @($(CHECKER) ./parse4 test3.xml) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./reader3 > reader3.tmp ; diff reader3.tmp reader3.res ; rm reader3.tmp) + @($(CHECKER) ./io2 > io2.tmp ; diff io2.tmp io2.res ; rm -f io2.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) - @(./io1 > io1.tmp ; diff io1.tmp io1.res ; rm -f io1.tmp) + @($(CHECKER) ./xpath2 test3.xml '//discarded' discarded > xpath2.tmp ; diff xpath2.tmp xpath2.res ; rm xpath2.tmp) @(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/doc/examples/examples.xml b/doc/examples/examples.xml index 9c14221..03f2db7 100644 --- a/doc/examples/examples.xml +++ b/doc/examples/examples.xml @@ -3,6 +3,7 @@ <synopsis>Evaluate XPath expression and prints result node set.</synopsis> <purpose>Shows how to evaluate XPath expression and register known namespaces in XPath context.</purpose> <usage>xpath1 <xml-file> <xpath-expr> [<known-ns-list>]</usage> + <test>./xpath1 test3.xml '//child2' > xpath1.tmp ; diff xpath1.tmp xpath1.res ; rm xpath1.tmp</test> <author>Aleksey Sanin</author> <copy>see Copyright for the status of this software. </copy> <section>XPath</section> @@ -13,27 +14,27 @@ <include><libxml/tree.h></include> </includes> <uses> - <enum line='228' file='tree' name='XML_ELEMENT_NODE'/> - <typedef line='87' file='xpath' name='xmlXPathObjectPtr'/> - <function line='53' file='xmlmemory' name='xmlMemoryDump'/> - <function line='116' file='xpath' name='xmlXPathEvalExpression'/> - <function line='185' file='xpathInternals' name='xmlXPathRegisterNs'/> - <function line='128' file='xpath' name='xmlXPathFreeObject'/> - <typedef line='85' file='tree' name='xmlDocPtr'/> - <typedef line='217' file='tree' name='xmlNsPtr'/> - <function line='100' file='xpath' name='xmlXPathNewContext'/> - <typedef line='205' file='tree' name='xmlNodePtr'/> - <function line='48' file='parser' name='xmlCleanupParser'/> - <macro line='42' file='xmlversion' name='LIBXML_TEST_VERSION'/> - <typedef line='86' file='xpath' name='xmlXPathContextPtr'/> - <function line='129' file='xpath' name='xmlXPathFreeContext'/> - <function line='38' file='parser' name='xmlInitParser'/> - <function line='155' file='xmlstring' name='xmlStrdup'/> - <function line='130' file='tree' name='xmlFreeDoc'/> - <function line='179' file='xmlstring' name='xmlStrchr'/> - <variable line='192' file='globals' name='xmlFree'/> - <function line='93' file='parser' name='xmlParseFile'/> - <enum line='216' file='tree' name='XML_NAMESPACE_DECL'/> + <enum line='229' file='tree' name='XML_ELEMENT_NODE'/> + <typedef line='88' file='xpath' name='xmlXPathObjectPtr'/> + <function line='54' file='xmlmemory' name='xmlMemoryDump'/> + <function line='117' file='xpath' name='xmlXPathEvalExpression'/> + <function line='186' file='xpathInternals' name='xmlXPathRegisterNs'/> + <function line='129' file='xpath' name='xmlXPathFreeObject'/> + <typedef line='86' file='tree' name='xmlDocPtr'/> + <typedef line='218' file='tree' name='xmlNsPtr'/> + <function line='101' file='xpath' name='xmlXPathNewContext'/> + <typedef line='206' file='tree' name='xmlNodePtr'/> + <function line='49' file='parser' name='xmlCleanupParser'/> + <macro line='43' file='xmlversion' name='LIBXML_TEST_VERSION'/> + <typedef line='87' file='xpath' name='xmlXPathContextPtr'/> + <function line='130' file='xpath' name='xmlXPathFreeContext'/> + <function line='39' file='parser' name='xmlInitParser'/> + <function line='156' file='xmlstring' name='xmlStrdup'/> + <function line='131' file='tree' name='xmlFreeDoc'/> + <function line='180' file='xmlstring' name='xmlStrchr'/> + <variable line='193' file='globals' name='xmlFree'/> + <function line='94' file='parser' name='xmlParseFile'/> + <enum line='217' file='tree' name='XML_NAMESPACE_DECL'/> </uses> </example> <example filename='parse1.c'> @@ -279,6 +280,90 @@ <typedef line='105' file='tree' name='xmlDocPtr'/> </uses> </example> + <example filename='parse3.c'> + <synopsis>Parse an XML document in memory to a tree and free it</synopsis> + <purpose>Demonstrate the use of xmlReadMemory() to read an XML file into a tree and and xmlFreeDoc() to free the resulting tree</purpose> + <usage>parse3</usage> + <test>parse3</test> + <author>Daniel Veillard</author> + <copy>see Copyright for the status of this software. </copy> + <section>Parsing</section> + <includes> + <include><libxml/tree.h></include> + <include><libxml/parser.h></include> + </includes> + <uses> + <function line='33' file='parser' name='xmlReadMemory'/> + </uses> + </example> + <example filename='parse4.c'> + <synopsis>Parse an XML document chunk by chunk to a tree and free it</synopsis> + <purpose>Demonstrate the use of xmlCreatePushParserCtxt() and xmlParseChunk() to read an XML file progressively into a tree and and xmlFreeDoc() to free the resulting tree</purpose> + <usage>parse4 test3.xml</usage> + <test>parse4 test3.xml</test> + <author>Daniel Veillard</author> + <copy>see Copyright for the status of this software. </copy> + <section>Parsing</section> + <includes> + <include><libxml/tree.h></include> + <include><libxml/parser.h></include> + </includes> + <uses> + <function line='93' file='parser' name='xmlFreeParserCtxt'/> + <function line='85' file='parser' name='xmlParseChunk'/> + <function line='66' file='parser' name='xmlCreatePushParserCtxt'/> + <typedef line='44' file='tree' name='xmlParserCtxtPtr'/> + </uses> + </example> + <example filename='io2.c'> + <synopsis>Output to char buffer</synopsis> + <purpose>Demonstrate the use of xmlDocDumpMemory to output document to a character buffer</purpose> + <usage>io2</usage> + <test>io2 > io2.tmp ; diff io2.tmp io2.res ; rm -f io2.tmp</test> + <author>John Fleck</author> + <copy>see Copyright for the status of this software. </copy> + <section>InputOutput</section> + <includes> + <include><libxml/parser.h></include> + </includes> + <uses> + <function line='27' file='tree' name='xmlNodeSetContent'/> + <function line='34' file='tree' name='xmlDocDumpFormatMemory'/> + <variable line='40' file='globals' name='xmlFree'/> + <function line='28' file='tree' name='xmlDocSetRootElement'/> + <typedef line='17' file='tree' name='xmlNodePtr'/> + <function line='25' file='tree' name='xmlNewDoc'/> + <function line='26' file='tree' name='xmlNewNode'/> + </uses> + </example> + <example filename='xpath2.c'> + <synopsis>Load a document, locate subelements with XPath, modify said elements and save the resulting document.</synopsis> + <purpose>Shows how to make a full round-trip from a load/edit/save</purpose> + <usage>xpath2 <xml-file> <xpath-expr> <new-value></usage> + <test>xpath2 test3.xml '//discarded' discarded > xpath2.tmp ; diff xpath2.tmp xpath2.res ; rm xpath2.tmp</test> + <author>Aleksey Sanin and Daniel Veillard</author> + <copy>see Copyright for the status of this software. </copy> + <section>XPath</section> + <includes> + <include><libxml/xpath.h></include> + <include><libxml/parser.h></include> + <include><libxml/xpathInternals.h></include> + <include><libxml/tree.h></include> + </includes> + <uses> + <function line='161' file='tree' name='xmlNodeSetContent'/> + <function line='126' file='tree' name='xmlDocDump'/> + <typedef line='87' file='xpath' name='xmlXPathObjectPtr'/> + <function line='109' file='xpath' name='xmlXPathEvalExpression'/> + <function line='122' file='xpath' name='xmlXPathFreeObject'/> + <function line='101' file='xpath' name='xmlXPathNewContext'/> + <typedef line='86' file='xpath' name='xmlXPathContextPtr'/> + <function line='123' file='xpath' name='xmlXPathFreeContext'/> + <function line='40' file='parser' name='xmlInitParser'/> + <enum line='179' file='tree' name='XML_NAMESPACE_DECL'/> + <function line='94' file='parser' name='xmlParseFile'/> + </uses> + </example> <symbols> <symbol name='LIBXML_TEST_VERSION'> <ref filename='xpath1.c'/> @@ -297,6 +382,7 @@ </symbol> <symbol name='XML_NAMESPACE_DECL'> <ref filename='xpath1.c'/> + <ref filename='xpath2.c'/> </symbol> <symbol name='XML_PARSE_DTDATTR'> <ref filename='reader2.c'/> @@ -334,12 +420,19 @@ <symbol name='xmlCreateIntSubset'> <ref filename='tree2.c'/> </symbol> + <symbol name='xmlCreatePushParserCtxt'> + <ref filename='parse4.c'/> + </symbol> <symbol name='xmlCtxtReadFile'> <ref filename='parse2.c'/> </symbol> <symbol name='xmlDocDump'> <ref filename='reader3.c'/> <ref filename='io1.c'/> + <ref filename='xpath2.c'/> + </symbol> + <symbol name='xmlDocDumpFormatMemory'> + <ref filename='io2.c'/> </symbol> <symbol name='xmlDocGetRootElement'> <ref filename='tree1.c'/> @@ -355,6 +448,7 @@ <symbol name='xmlDocSetRootElement'> <ref filename='tree2.c'/> <ref filename='testWriter.c'/> + <ref filename='io2.c'/> </symbol> <symbol name='xmlFindCharEncodingHandler'> <ref filename='testWriter.c'/> @@ -362,6 +456,7 @@ <symbol name='xmlFree'> <ref filename='xpath1.c'/> <ref filename='testWriter.c'/> + <ref filename='io2.c'/> </symbol> <symbol name='xmlFreeDoc'> <ref filename='xpath1.c'/> @@ -373,6 +468,7 @@ </symbol> <symbol name='xmlFreeParserCtxt'> <ref filename='parse2.c'/> + <ref filename='parse4.c'/> </symbol> <symbol name='xmlFreeTextReader'> <ref filename='reader1.c'/> @@ -384,6 +480,7 @@ </symbol> <symbol name='xmlInitParser'> <ref filename='xpath1.c'/> + <ref filename='xpath2.c'/> </symbol> <symbol name='xmlMalloc'> <ref filename='testWriter.c'/> @@ -402,12 +499,14 @@ <symbol name='xmlNewDoc'> <ref filename='tree2.c'/> <ref filename='testWriter.c'/> + <ref filename='io2.c'/> </symbol> <symbol name='xmlNewDocNode'> <ref filename='testWriter.c'/> </symbol> <symbol name='xmlNewNode'> <ref filename='tree2.c'/> + <ref filename='io2.c'/> </symbol> <symbol name='xmlNewParserCtxt'> <ref filename='parse2.c'/> @@ -433,22 +532,33 @@ <symbol name='xmlNodePtr'> <ref filename='xpath1.c'/> <ref filename='testWriter.c'/> + <ref filename='io2.c'/> + </symbol> + <symbol name='xmlNodeSetContent'> + <ref filename='io2.c'/> + <ref filename='xpath2.c'/> </symbol> <symbol name='xmlNsPtr'> <ref filename='xpath1.c'/> </symbol> + <symbol name='xmlParseChunk'> + <ref filename='parse4.c'/> + </symbol> <symbol name='xmlParseFile'> <ref filename='xpath1.c'/> <ref filename='tree1.c'/> + <ref filename='xpath2.c'/> </symbol> <symbol name='xmlParserCtxtPtr'> <ref filename='parse2.c'/> + <ref filename='parse4.c'/> </symbol> <symbol name='xmlReadFile'> <ref filename='parse1.c'/> </symbol> <symbol name='xmlReadMemory'> <ref filename='io1.c'/> + <ref filename='parse3.c'/> </symbol> <symbol name='xmlReaderForFile'> <ref filename='reader1.c'/> @@ -555,21 +665,27 @@ </symbol> <symbol name='xmlXPathContextPtr'> <ref filename='xpath1.c'/> + <ref filename='xpath2.c'/> </symbol> <symbol name='xmlXPathEvalExpression'> <ref filename='xpath1.c'/> + <ref filename='xpath2.c'/> </symbol> <symbol name='xmlXPathFreeContext'> <ref filename='xpath1.c'/> + <ref filename='xpath2.c'/> </symbol> <symbol name='xmlXPathFreeObject'> <ref filename='xpath1.c'/> + <ref filename='xpath2.c'/> </symbol> <symbol name='xmlXPathNewContext'> <ref filename='xpath1.c'/> + <ref filename='xpath2.c'/> </symbol> <symbol name='xmlXPathObjectPtr'> <ref filename='xpath1.c'/> + <ref filename='xpath2.c'/> </symbol> <symbol name='xmlXPathRegisterNs'> <ref filename='xpath1.c'/> @@ -578,10 +694,13 @@ <sections> <section name='InputOutput'> <example filename='io1.c'/> + <example filename='io2.c'/> </section> <section name='Parsing'> <example filename='parse1.c'/> <example filename='parse2.c'/> + <example filename='parse3.c'/> + <example filename='parse4.c'/> </section> <section name='Tree'> <example filename='tree1.c'/> @@ -589,6 +708,7 @@ </section> <section name='XPath'> <example filename='xpath1.c'/> + <example filename='xpath2.c'/> </section> <section name='xmlReader'> <example filename='reader1.c'/> diff --git a/doc/examples/examples.xsl b/doc/examples/examples.xsl index e4ccfd3..74aaaa2 100644 --- a/doc/examples/examples.xsl +++ b/doc/examples/examples.xsl @@ -99,6 +99,11 @@ <xsl:apply-templates select='.'/> </xsl:for-each> </ul> + <p> Getting the compilation options and libraries dependancies needed +to generate binaries from the examples is best done on Linux/Unix by using +the xml2-config script which should have been installed as part of <i>make +install</i> step or when installing the libxml2 development package:</p> +<pre>gcc -o example `xml2-config --cflags` example.c `xml2-config --libs`</pre> </xsl:template> <xsl:template name="sections-list"> diff --git a/doc/examples/index.py b/doc/examples/index.py index c3a85de..466cfc9 100755 --- a/doc/examples/index.py +++ b/doc/examples/index.py @@ -249,10 +249,11 @@ install-data-local: for example in examples: Makefile = Makefile + "%s_SOURCES=%s.c\n%s_LDFLAGS=\n%s_DEPENDENCIES= $(DEPS)\n%s_LDADD= @RDL_LIBS@ $(LDADDS)\n\n" % (example, example, example, example, example) + Makefile = Makefile + "valgrind: \n\t$(MAKE) CHECKER='valgrind -q' tests\n\n" Makefile = Makefile + "tests: $(noinst_PROGRAMS)\n" Makefile = Makefile + "\t@(echo > .memdump)\n" for test in tests: - Makefile = Makefile + "\t@(%s)\n" % (test) + Makefile = Makefile + "\t@($(CHECKER) %s)\n" % (test) Makefile = Makefile + '\t@(grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0" ; exit 0)\n' Makefile = Makefile + "\n\n" try: diff --git a/doc/examples/io2.c b/doc/examples/io2.c new file mode 100644 index 0000000..59dede2 --- /dev/null +++ b/doc/examples/io2.c @@ -0,0 +1,45 @@ +/** + * section: InputOutput + * synopsis: Output to char buffer + * purpose: Demonstrate the use of xmlDocDumpMemory + * to output document to a character buffer + * usage: io2 + * test: io2 > io2.tmp ; diff io2.tmp io2.res ; rm -f io2.tmp + * author: John Fleck + * copy: see Copyright for the status of this software. + */ + +#include <libxml/parser.h> + +int +main(void) { + + xmlNodePtr n; + xmlDocPtr doc; + xmlChar *xmlbuff; + int buffersize; + + /* + * Create the document. + */ + doc = xmlNewDoc(BAD_CAST "1.0"); + n = xmlNewNode(NULL, BAD_CAST "root"); + xmlNodeSetContent(n, BAD_CAST "content"); + xmlDocSetRootElement(doc,n); + + /* + * Dump the document to a buffer and print it + * for demonstration purposes. + */ + xmlDocDumpFormatMemory (doc, &xmlbuff, &buffersize, 1); + printf ((char *)xmlbuff); + + /* + * Free associated memory. + */ + xmlFree (xmlbuff); + xmlFreeDoc(doc); + + return(0); + +} diff --git a/doc/examples/io2.res b/doc/examples/io2.res new file mode 100644 index 0000000..8737b87 --- /dev/null +++ b/doc/examples/io2.res @@ -0,0 +1,2 @@ +<?xml version="1.0"?> +<root>content</root> diff --git a/doc/examples/parse3.c b/doc/examples/parse3.c new file mode 100644 index 0000000..a2d3a40 --- /dev/null +++ b/doc/examples/parse3.c @@ -0,0 +1,60 @@ +/** + * section: Parsing + * synopsis: Parse an XML document in memory to a tree and free it + * purpose: Demonstrate the use of xmlReadMemory() to read an XML file + * into a tree and and xmlFreeDoc() to free the resulting tree + * usage: parse3 + * test: parse3 + * author: Daniel Veillard + * copy: see Copyright for the status of this software. + */ + +#include <stdio.h> +#include <libxml/parser.h> +#include <libxml/tree.h> + +static const char *document = "<doc/>"; + +/** + * example3Func: + * @content: the content of the document + * @length: the length in bytes + * + * Parse the in memory document and free the resulting tree + */ +static void +example3Func(const char *content, int length) { + xmlDocPtr doc; /* the resulting document tree */ + + /* + * The document being in memory, it have no base per RFC 2396, + * and the "noname.xml" argument will serve as its base. + */ + doc = xmlReadMemory(content, length, "noname.xml", NULL, 0); + if (doc == NULL) { + fprintf(stderr, "Failed to parse document\n"); + return; + } + xmlFreeDoc(doc); +} + +int main(void) { + /* + * this initialize the library and check potential ABI mismatches + * between the version it was compiled for and the actual shared + * library used. + */ + LIBXML_TEST_VERSION + + example3Func(document, 6); + + /* + * Cleanup function for the XML library. + */ + xmlCleanupParser(); + /* + * this is to debug memory for regression tests + */ + xmlMemoryDump(); + return(0); +} diff --git a/doc/examples/parse4.c b/doc/examples/parse4.c new file mode 100644 index 0000000..fe57894 --- /dev/null +++ b/doc/examples/parse4.c @@ -0,0 +1,136 @@ +/** + * section: Parsing + * synopsis: Parse an XML document chunk by chunk to a tree and free it + * purpose: Demonstrate the use of xmlCreatePushParserCtxt() and + * xmlParseChunk() to read an XML file progressively + * into a tree and and xmlFreeDoc() to free the resulting tree + * usage: parse4 test3.xml + * test: parse4 test3.xml + * author: Daniel Veillard + * copy: see Copyright for the status of this software. + */ + +#include <stdio.h> +#include <libxml/parser.h> +#include <libxml/tree.h> + +static FILE *desc; + +/** + * readPacket: + * @mem: array to store the packet + * @size: the packet size + * + * read at most @size bytes from the document and store it in @mem + * + * Returns the number of bytes read + */ +static int +readPacket(char *mem, int size) { + int res; + + res = fread(mem, 1, size, desc); + return(res); +} + +/** + * example4Func: + * @filename: a filename or an URL + * + * Parse the resource and free the resulting tree + */ +static void +example4Func(const char *filename) { + xmlParserCtxtPtr ctxt; + char chars[4]; + xmlDocPtr doc; /* the resulting document tree */ + int res; + + /* + * Read a few first byte to check the input used for the + * encoding detection at the parser level. + */ + res = readPacket(chars, 4); + if (res <= 0) { + fprintf(stderr, "Failed to parse %s\n", filename); + return; + } + + /* + * Create a progressive parsing context, the 2 first arguments + * are not used since we want to build a tree and not use a SAX + * parsing interface. We also pass the first bytes of the document + * to allow encoding detection when creating the parser but this + * is optional. + */ + ctxt = xmlCreatePushParserCtxt(NULL, NULL, + chars, res, filename); + if (ctxt == NULL) { + fprintf(stderr, "Failed to create parser context !\n"); + return; + } + + /* + * loop on the input getting the document data, of course 4 bytes + * at a time is not realistic but allows to verify testing on small + * documents. + */ + while ((res = readPacket(chars, 4)) > 0) { + xmlParseChunk(ctxt, chars, res, 0); + } + + /* + * there is no more input, indicate the parsing is finished. + */ + xmlParseChunk(ctxt, chars, 0, 1); + + /* + * collect the document back and if it was wellformed + * and destroy the parser context. + */ + doc = ctxt->myDoc; + res = ctxt->wellFormed; + xmlFreeParserCtxt(ctxt); + + if (!res) { + fprintf(stderr, "Failed to parse %s\n", filename); + } + + /* + * since we don't use the document, destroy it now. + */ + xmlFreeDoc(doc); +} + +int main(int argc, char **argv) { + if (argc != 2) + return(1); + + /* + * this initialize the library and check potential ABI mismatches + * between the version it was compiled for and the actual shared + * library used. + */ + LIBXML_TEST_VERSION + + /* + * simulate a progressive parsing using the input file. + */ + desc = fopen(argv[1], "rb"); + if (desc != NULL) { + example4Func(argv[1]); + fclose(desc); + } else { + fprintf(stderr, "Failed to parse %s\n", argv[1]); + } + + /* + * Cleanup function for the XML library. + */ + xmlCleanupParser(); + /* + * this is to debug memory for regression tests + */ + xmlMemoryDump(); + return(0); +} diff --git a/doc/examples/tst.xml b/doc/examples/tst.xml new file mode 100644 index 0000000..1cc6c95 --- /dev/null +++ b/doc/examples/tst.xml @@ -0,0 +1,7 @@ +<thing> + <thing1>hello</thing1> +</thing> +<thing> + <thing2>goodbye</thing2> +</thing> + diff --git a/doc/examples/xpath1.c b/doc/examples/xpath1.c index 0e49737..f014b7b 100644 --- a/doc/examples/xpath1.c +++ b/doc/examples/xpath1.c @@ -4,6 +4,7 @@ * purpose: Shows how to evaluate XPath expression and register * known namespaces in XPath context. * usage: xpath1 <xml-file> <xpath-expr> [<known-ns-list>] + * test: ./xpath1 test3.xml '//child2' > xpath1.tmp ; diff xpath1.tmp xpath1.res ; rm xpath1.tmp * author: Aleksey Sanin * copy: see Copyright for the status of this software. */ diff --git a/doc/examples/xpath1.res b/doc/examples/xpath1.res new file mode 100644 index 0000000..76af3a9 --- /dev/null +++ b/doc/examples/xpath1.res @@ -0,0 +1,5 @@ +Result (4 nodes): += element node "child2" += element node "child2" += element node "child2" += element node "child2" diff --git a/doc/examples/xpath2.c b/doc/examples/xpath2.c new file mode 100644 index 0000000..70e5e61 --- /dev/null +++ b/doc/examples/xpath2.c @@ -0,0 +1,189 @@ +/** + * section: XPath + * synopsis: Load a document, locate subelements with XPath, modify + * said elements and save the resulting document. + * purpose: Shows how to make a full round-trip from a load/edit/save + * usage: xpath2 <xml-file> <xpath-expr> <new-value> + * test: xpath2 test3.xml '//discarded' discarded > xpath2.tmp ; diff xpath2.tmp xpath2.res ; rm xpath2.tmp + * author: Aleksey Sanin and Daniel Veillard + * copy: see Copyright for the status of this software. + */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <libxml/tree.h> +#include <libxml/parser.h> +#include <libxml/xpath.h> +#include <libxml/xpathInternals.h> + +#ifdef LIBXML_XPATH_ENABLED + + +static void usage(const char *name); +static int example4(const char *filename, const xmlChar * xpathExpr, + const xmlChar * value); +static void update_xpath_nodes(xmlNodeSetPtr nodes, const xmlChar * value); + + +int +main(int argc, char **argv) { + /* Parse command line and process file */ + if (argc != 4) { + fprintf(stderr, "Error: wrong number of arguments.\n"); + usage(argv[0]); + return(-1); + } + + /* Init libxml */ + xmlInitParser(); + LIBXML_TEST_VERSION + + /* Do the main job */ + if (example4(argv[1], BAD_CAST argv[2], BAD_CAST argv[3])) { + usage(argv[0]); + return(-1); + } + + /* Shutdown libxml */ + xmlCleanupParser(); + + /* + * this is to debug memory for regression tests + */ + xmlMemoryDump(); + return 0; +} + +/** + * usage: + * @name: the program name. + * + * Prints usage information. + */ +void +usage(const char *name) { + assert(name); + + fprintf(stderr, "Usage: %s <xml-file> <xpath-expr> <value>\n", name); +} + +/** + * example4: + * @filename: the input XML filename. + * @xpathExpr: the xpath expression for evaluation. + * @value: the new node content. + * + * Parses input XML file, evaluates XPath expression and update the nodes + * then print the result. + * + * Returns 0 on success and a negative value otherwise. + */ +static int +example4(const char* filename, const xmlChar* xpathExpr, const xmlChar* value) { + xmlDocPtr doc; + xmlXPathContextPtr xpathCtx; + xmlXPathObjectPtr xpathObj; + + assert(filename); + assert(xpathExpr); + assert(value); + + /* Load XML document */ + doc = xmlParseFile(filename); + if (doc == NULL) { + fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename); + return(-1); + } + + /* Create xpath evaluation context */ + xpathCtx = xmlXPathNewContext(doc); + if(xpathCtx == NULL) { + fprintf(stderr,"Error: unable to create new XPath context\n"); + xmlFreeDoc(doc); + return(-1); + } + + /* Evaluate xpath expression */ + xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); + if(xpathObj == NULL) { + fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr); + xmlXPathFreeContext(xpathCtx); + xmlFreeDoc(doc); + return(-1); + } + + /* update selected nodes */ + update_xpath_nodes(xpathObj->nodesetval, value); + + + /* Cleanup of XPath data */ + xmlXPathFreeObject(xpathObj); + xmlXPathFreeContext(xpathCtx); + + /* dump the resulting document */ + xmlDocDump(stdout, doc); + + + /* free the document */ + xmlFreeDoc(doc); + + return(0); +} + +/** + * update_xpath_nodes: + * @nodes: the nodes set. + * @value: the new value for the node(s) + * + * Prints the @nodes content to @output. + */ +static void +update_xpath_nodes(xmlNodeSetPtr nodes, const xmlChar* value) { + int size; + int i; + + assert(value); + size = (nodes) ? nodes->nodeNr : 0; + + /* + * NOTE: the nodes are processed in reverse order, i.e. reverse document + * order because xmlNodeSetContent can actually free up descendant + * of the node and such nodes may have been selected too ! Handling + * in reverse order ensure that descendant are accessed first, before + * they get removed. Mixing XPath and modifications on a tree must be + * done carefully ! + */ + for(i = size - 1; i >= 0; i--) { + assert(nodes->nodeTab[i]); + + xmlNodeSetContent(nodes->nodeTab[i], value); + /* + * All the elements returned by an XPath query are pointers to + * elements from the tree *except* namespace nodes where the XPath + * semantic is different from the implementation in libxml2 tree. + * As a result when a returned node set is freed when + * xmlXPathFreeObject() is called, that routine must check the + * element type. But node from the returned set may have been removed + * by xmlNodeSetContent() resulting in access to freed data. + * This can be exercised by running + * valgrind xpath2 test3.xml '//discarded' discarded + * There is 2 ways around it: + * - make a copy of the pointers to the nodes from the result set + * then call xmlXPathFreeObject() and then modify the nodes + * or + * - remove the reference to the modified nodes from the node set + * as they are processed, if they are not namespace nodes. + */ + if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL) + nodes->nodeTab[i] = NULL; + } +} + +#else +int main(void) { + fprintf(stderr, "XPath support not compiled in\n"); + exit(1); +} +#endif diff --git a/doc/examples/xpath2.res b/doc/examples/xpath2.res new file mode 100644 index 0000000..4e89699 --- /dev/null +++ b/doc/examples/xpath2.res @@ -0,0 +1,30 @@ +<?xml version="1.0"?> +<doc> + <parent> + <discarded>discarded</discarded> + <preserved/> + This text node must be discarded + <discarded>discarded</discarded> + <preserved> + content1 + <child1/> + <child2>content2</child2> + <preserved>too</preserved> + <child2>content3</child2> + <preserved/> + <child2>content4</child2> + <preserved/> + <child2>content5</child2> + content6 + </preserved> + This text node must be discarded + <discarded>discarded</discarded> + This text node must be discarded + <preserved/> + This text node must be discarded + <preserved/> + This text node must be discarded + <discarded>discarded</discarded> + This text node must be discarded + </parent> +</doc> |