1 /*   xlint.c
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *            National Center for Biotechnology Information (NCBI)
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government do not place any restriction on its use or reproduction.
13 *  We would, however, appreciate having the NCBI and the author cited in
14 *  any work or product based on this material
15 *
16 *  Although all reasonable efforts have been taken to ensure the accuracy
17 *  and reliability of the software and data, the NLM and the U.S.
18 *  Government do not and cannot warrant the performance or results that
19 *  may be obtained by using this software or data. The NLM and the U.S.
20 *  Government disclaim all warranties, express or implied, including
21 *  warranties of performance, merchantability or fitness for any particular
22 *  purpose.
23 *
24 * ===========================================================================
25 *
26 * File Name:  xlint.c
27 *
28 * Author:  Jonathan Kans
29 *
30 * Version Creation Date:   4/22/11
31 *
32 * $Revision: 1.2 $
33 *
34 * File Description:
35 *
36 *  Lint for XML
37 *
38 * Modifications:
39 * --------------------------------------------------------------------------
40 * Date     Name        Description of modification
41 * -------  ----------  -----------------------------------------------------
42 *
43 *
44 * ==========================================================================
45 */
46 
47 #include <ncbi.h>
48 #include <urlquery.h>
49 
WriteStringCallback(XmlObjPtr xop,XmlObjPtr parent,Int2 level,Pointer userdata)50 static void WriteStringCallback (XmlObjPtr xop, XmlObjPtr parent, Int2 level, Pointer userdata)
51 
52 {
53   FILE  *ofp;
54 
55   if (xop == NULL || userdata == NULL) return;
56   ofp = (FILE*) userdata;
57 
58   if (StringHasNoText (xop->contents)) return;
59 
60   fprintf (ofp, "%s\n", xop->contents);
61 }
62 
63 #define i_argInputFile    0
64 #define o_argOutputFile   1
65 #define s_argAltSelf      2
66 #define t_argUseTabs      3
67 #define n_argNodeFilter   4
68 #define p_argParentFilter 5
69 #define a_argAttTagFilter 6
70 #define v_argAttValFilter 7
71 
72 Args myargs [] = {
73   {"Input File", "stdin", NULL, NULL,
74     FALSE, 'i', ARG_FILE_IN, 0.0, 0, NULL},
75   {"Output File", "stdout", NULL, NULL,
76     FALSE, 'o', ARG_FILE_OUT, 0.0, 0, NULL},
77   {"Self-Closing Tag Alternative Style", "F", NULL, NULL,
78     TRUE, 's', ARG_BOOLEAN, 0.0, 0, NULL},
79   {"Indent with Tabs instead of Spaces", "F", NULL, NULL,
80     TRUE, 't', ARG_BOOLEAN, 0.0, 0, NULL},
81   {"Node Filter", NULL, NULL, NULL,
82     TRUE, 'n', ARG_STRING, 0.0, 0, NULL},
83   {"Parent Filter", NULL, NULL, NULL,
84     TRUE, 'p', ARG_STRING, 0.0, 0, NULL},
85   {"Attribute Tag Filter", NULL, NULL, NULL,
86     TRUE, 'a', ARG_STRING, 0.0, 0, NULL},
87   {"Attribute Value Filter", NULL, NULL, NULL,
88     TRUE, 'v', ARG_STRING, 0.0, 0, NULL},
89 };
90 
Main(void)91 Int2 Main (void)
92 
93 {
94   Boolean     altSelf, useTabs;
95   FileCache   fc;
96   FILE        *ifp, *ofp;
97   CharPtr     infile, outfile, str;
98   Char        line [4096];
99   CharPtr     nodeFilt, argFilt, attFilt, valFilt;
100   ValNodePtr  head = NULL, tail = NULL;
101   XmlObjPtr   xop;
102 
103   ErrSetFatalLevel (SEV_MAX);
104   ErrClearOptFlags (EO_SHOW_USERSTR);
105   ErrPathReset ();
106 
107   if (! GetArgs ("xlint", sizeof (myargs) / sizeof (Args), myargs)) {
108     return 0;
109   }
110 
111   infile = (CharPtr) myargs [i_argInputFile].strvalue;
112   outfile = (CharPtr) myargs [o_argOutputFile].strvalue;
113   altSelf = (Boolean) myargs [s_argAltSelf].intvalue;
114   useTabs = (Boolean) myargs [t_argUseTabs].intvalue;
115 
116   nodeFilt = (CharPtr) myargs [n_argNodeFilter].strvalue;
117   argFilt = (CharPtr) myargs [p_argParentFilter].strvalue;
118   attFilt = (CharPtr) myargs [a_argAttTagFilter].strvalue;
119   valFilt = (CharPtr) myargs [v_argAttValFilter].strvalue;
120 
121   if (StringHasNoText (infile)) return 1;
122   if (StringHasNoText (outfile)) return 1;
123 
124   ifp = FileOpen (infile, "r");
125   if (ifp == NULL) {
126     Message (MSG_FATAL, "Unable to open input file");
127     return 1;
128   }
129 
130   ofp = FileOpen (outfile, "w");
131   if (ofp == NULL) {
132     Message (MSG_FATAL, "Unable to open output file");
133     return 1;
134   }
135 
136   FileCacheSetup (&fc, ifp);
137   str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
138   while (str != NULL) {
139     if (StringDoesHaveText (str)) {
140       ValNodeCopyStrEx (&head, &tail, 0, str);
141     }
142     str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
143   }
144 
145   if (head == NULL) {
146     Message (MSG_FATAL, "Unable to read input file");
147     return 1;
148   }
149 
150   str = ValNodeMergeStrs (head);
151   ValNodeFreeData (head);
152 
153   if (str == NULL) {
154     Message (MSG_FATAL, "Unable to merge valnodes");
155     return 1;
156   }
157 
158   xop = ParseXmlString (str);
159   if (xop == NULL) {
160     Message (MSG_FATAL, "Unable to ParseXmlString");
161     return 1;
162   }
163 
164   if (StringDoesHaveText (nodeFilt) ||
165       StringDoesHaveText (argFilt) ||
166       StringDoesHaveText (attFilt) ||
167       StringDoesHaveText (valFilt)) {
168     VisitXmlNodes (xop, (Pointer) ofp, WriteStringCallback, nodeFilt, argFilt, attFilt, valFilt, 0);
169   } else {
170     WriteXmlObjectEx (xop, ofp, useTabs, altSelf);
171   }
172 
173   FreeXmlObject (xop);
174 
175   MemFree (str);
176 
177   FileClose (ofp);
178 
179   return 0;
180 }
181 
182