Java 使用XMLInputFormat在hadoop中解析xml时不执行hadoop映射器类

Java 使用XMLInputFormat在hadoop中解析xml时不执行hadoop映射器类,java,hadoop,xml-parsing,mapreduce,mahout,Java,Hadoop,Xml Parsing,Mapreduce,Mahout,我是hadoop新手,使用hadoop 2.6.0版本并尝试解析复杂的XML。 搜索了一段时间后,我了解到,对于XML解析,我们需要编写自定义InputFormat,这是mahout的XMLInputFormat。 我还得到了他的帮助 但是,当我在passig XMLInputformat类之后运行代码时,如果使用示例中给出的XMLInputformat,它将不会调用我自己的映射器类,并且输出文件中包含0个数据 令人惊讶的是,如果我没有将XMLInputFormat类传递给我的作业,那么我的映射

我是hadoop新手,使用hadoop 2.6.0版本并尝试解析复杂的XML。 搜索了一段时间后,我了解到,对于XML解析,我们需要编写自定义InputFormat,这是mahout的XMLInputFormat。 我还得到了他的帮助

但是,当我在passig XMLInputformat类之后运行代码时,如果使用示例中给出的XMLInputformat,它将不会调用我自己的映射器类,并且输出文件中包含0个数据

令人惊讶的是,如果我没有将XMLInputFormat类传递给我的作业,那么我的映射器工作正常并正确地给出输出。有人能帮我指出我在这里遗漏了什么吗

我的作业配置类是:

public static void runParserJob(String inputPath, String outputPath) throws IOException {
    LOGGER.info("-----runParserJob()-----Start");
    Configuration configuration = new Configuration();         configuration.set("xmlinput.start",Constants.XML_INPUT_START_TAG_PRODUCT);
    configuration.set("xmlinput.end",Constants.XML_INPUT_END_TAG_PRODUCT);
    configuration.set("io.serializations",Constants.XML_IO_SERIALIZATIONS);

    Job job = new Job(configuration,Constants.JOB_TITLE);
    FileInputFormat.setInputPaths(job, inputPath);
    job.setJarByClass(ParserDriver.class);
    job.setMapperClass(XMLMapper.class);
    job.setNumReduceTasks(0);
    job.setInputFormatClass(XmlInputFormat.class);
    job.setOutputKeyClass(NullWritable.class);
    job.setOutputValueClass(Text.class);
    Path hdfsOutputPath = new Path(outputPath);
    FileOutputFormat.setOutputPath(job, hdfsOutputPath);
    FileSystem dfs = FileSystem.get(hdfsOutputPath.toUri(),configuration);
    /**Using this condition it will create output at same location 
     * by deleting older data in that location**/
    if(dfs.exists(hdfsOutputPath)){
        dfs.delete(hdfsOutputPath,true);
    }
    try{
        job.waitForCompletion(true);
    }catch(InterruptedException ie){
        LOGGER.error("-----Process interrupted in between Exception-----", ie);
    }catch(ClassNotFoundException ce){
        LOGGER.error("-----Class not found while running the job-----",ce);
    }
}
我的XMLInputFormat类是:

public class XmlInputFormat extends TextInputFormat{

public static final String START_TAG_KEY = "xmlinput.start";
public static final String END_TAG_KEY = "xmlinput.end";

@Override
public RecordReader<LongWritable,Text> createRecordReader(InputSplit is, TaskAttemptContext tac)  {
    return new XmlRecordReader();
}

public static class XmlRecordReader extends RecordReader<LongWritable, Text>{
    private byte[] startTag;
    private byte[] endTag;
    private long start;
    private long end;
    private FSDataInputStream fsin;
    private DataOutputBuffer buffer = new DataOutputBuffer();
    private LongWritable key = new LongWritable();
    private Text value = new Text();

    @Override
    public void initialize(InputSplit inputSplit, TaskAttemptContext taskAttemptContext)
            throws IOException, InterruptedException {
        FileSplit fileSplit = (FileSplit)inputSplit;
        startTag = taskAttemptContext.getConfiguration().get(START_TAG_KEY).getBytes("utf-8");
        endTag = taskAttemptContext.getConfiguration().get(END_TAG_KEY).getBytes("utf-8");

        start = fileSplit.getStart();
        end = start + fileSplit.getLength();
        Path file = fileSplit.getPath();

        FileSystem hdfs = file.getFileSystem(taskAttemptContext.getConfiguration());
         fsin = hdfs.open(fileSplit.getPath());
         fsin.seek(start);
    }

    @Override
    public boolean nextKeyValue() throws IOException, InterruptedException {
        if(fsin.getPos() < end){
            if(readUntilMatch(startTag,false)){
              try {
                    buffer.write(startTag);
                    if (readUntilMatch(endTag, true)) {
                        value.set(buffer.getData(), 0, buffer.getLength());
                        key.set(fsin.getPos());
                        return true;
                    }
                  } finally {
                    buffer.reset();
                  }
            }
        }
        return false;
    }

    @Override
    public void close() throws IOException {

    }

    @Override
    public LongWritable getCurrentKey() throws IOException,InterruptedException {
        return null;
    }

    @Override
    public Text getCurrentValue() throws IOException, InterruptedException {
        return null;
    }

    @Override
    public float getProgress() throws IOException, InterruptedException {
        return 0;
    }

    private boolean readUntilMatch(byte[] match, boolean withinBlock) throws IOException{
        int i = 0;
        while(true){
            int b = fsin.read();
            //If reaches to EOF
            if(b == -1){
                return false;
            }   
            //If not then save into the buffer.
            if(withinBlock){
                buffer.write(b);
            }
            // check if we're matching:
            if (b == match[i]) {
              i++;
              if (i >= match.length) return true;
            } else i = 0;
            // see if we've passed the stop point:
            if (!withinBlock && i == 0 && fsin.getPos() >= end) return false;
        }
    }

}
公共类XmlInputFormat扩展了TextInputFormat{
公共静态最终字符串START\u TAG\u KEY=“xmlinput.START”;
公共静态最终字符串END_TAG_KEY=“xmlinput.END”;
@凌驾
公共RecordReader createRecordReader(InputSplit是,TaskAttemptContext tac){
返回新的XmlRecordReader();
}
公共静态类XmlRecordReader扩展了RecordReader{
专用字节[]startTag;
私有字节[]endTag;
私人长期启动;
私人长尾;
私有FSDataInputStream-fsin;
私有DataOutputBuffer=新DataOutputBuffer();
私有LongWritable密钥=新的LongWritable();
私有文本值=新文本();
@凌驾
公共void初始化(InputSplit InputSplit,TaskAttemptContext TaskAttemptContext)
抛出IOException、InterruptedException{
FileSplit FileSplit=(FileSplit)inputSplit;
startTag=taskAttemptContext.getConfiguration().get(开始标记键).getBytes(“utf-8”);
endTag=taskAttemptContext.getConfiguration().get(END_TAG_KEY).getBytes(“utf-8”);
start=fileSplit.getStart();
end=start+fileSplit.getLength();
Path file=fileSplit.getPath();
FileSystem hdfs=file.getFileSystem(taskAttemptContext.getConfiguration());
fsin=hdfs.open(fileSplit.getPath());
fsin.seek(启动);
}
@凌驾
公共布尔值nextKeyValue()引发IOException、InterruptedException{
if(fsin.getPos()=match.length)返回true;
}否则i=0;
//看看我们是否通过了停车点:
如果(!withinBlock&&i==0&&fsin.getPos()>=end)返回false;
}
}
}
}



有人能帮我吗?提前谢谢。如果我在任何地方出错,请纠正我。

我不确定您的XML结构是什么样子,但例如,如果您有一个XML结构:

<data>
   <product id="101" itemCategory="BER" transaction="PUR">
       <transaction-id>102A5RET</transaction-id>
       <item-name>Blue-Moon-12-PK-BTTLE</item-name>
       <item-purchased>2</item-purchased>
       <item-price>12.99</item-price>
       <time-stamp>2015-04-20 11:12:13 102301</time-stamp>
   </product>
   .
   .
   .
</data>

102A5RET
蓝月亮-12-PK-BTTLE
2.
12.99
2015-04-20 11:12:13 102301
.
.
.
XMLInputFormat类需要知道要使用哪个XML节点:

configuration.set("xmlinput.start", "<product") //note only <product
configuration.set("xmlinput.end", "</product>") //note only </product>

configuration.set(“xmlinput.start”,“我也做了同样的操作,但现在的问题是,例如,标记包含属性。与您的示例中相同。而且,在标记中还有一个标记没有属性。我想遍历包含属性的上部标记。但我没有找到遍历它的方法。我的错误是,我给了”“而不是”