/// <summary> /// Extrae el texto con los patrones aprendidos con tal de comparar si son falsos positivos. /// </summary> /// <param name="checkResult">PdfCheckResult para comparar los falsos positivos.</param> /// <returns></returns> public List <PdfTagPattern> ExtractToCheck(PdfCheckResult checkResult) { PdfTagExtractionResult result = new PdfTagExtractionResult() { Pdf = checkResult.Pdf, MetadataType = Type.GetType(MetadataName) }; _Converters = new Dictionary <Type, object>(); IHierarchySet hierarchySet = GetHierarchySet(); foreach (var page in checkResult.Pdf.PdfUnstructuredPages) { ExtractFromRectangles(page.WordGroups, result.MetadataType, hierarchySet, result, page.PdfPageN); ExtractFromRectangles(page.Lines, result.MetadataType, hierarchySet, result, page.PdfPageN, "LinesInfos"); ExtractFromText(result.MetadataType, result, page, hierarchySet); ExtractFromColorFontText(page.ColorFontWordGroups, result.MetadataType, hierarchySet, result, page.PdfPageN); } result.Converters = _Converters; return(result.CheckWithRightMetadata(checkResult.InvoiceMetadata)); // Comprobamos que los patrones que pasemos como resultado hayan extraído el texto correctamente. }
/// <summary> /// Ejecuta patrones los extracción de textos /// almacenados. /// </summary> /// <param name="pdf"></param> /// <returns></returns> public PdfTagExtractionResult Extract(PdfUnstructuredDoc pdf) { PdfTagExtractionResult result = new PdfTagExtractionResult() { Pdf = pdf, MetadataType = Type.GetType(MetadataName) }; _Converters = new Dictionary <Type, object>(); IHierarchySet hierarchySet = GetHierarchySet(); foreach (var page in pdf.PdfUnstructuredPages) { ExtractFromRectangles(page.WordGroups, result.MetadataType, hierarchySet, result); ExtractFromRectangles(page.Lines, result.MetadataType, hierarchySet, result, "LinesInfos"); ExtractFromText(result.MetadataType, result, page, hierarchySet); ExtractFromTextStrings(page.TextStringGroups, result.MetadataType, hierarchySet, result); } result.Converters = _Converters; result.GetMetadata(); return(result); }
/// <summary> /// Ejecuta los patrones de extracción de textos /// almacenados. /// </summary> /// <param name="pdf">Archivo PDF sobre el que extraer.</param> /// <returns></returns> public PdfTagExtractionResult Extract(PdfUnstructuredDoc pdf) { PdfTagExtractionResult result = new PdfTagExtractionResult() { Pdf = pdf, MetadataType = Type.GetType(MetadataName) }; _Converters = new Dictionary <Type, object>(); IHierarchySet hierarchySet = GetHierarchySet(); PdfPatternsPage = new Dictionary <int, List <PdfTagPattern> >(); foreach (PdfTagPattern pattern in PdfPatterns) // Evitar que los bucles de extracción recorran siempre todos los patrones idependientemente del número de página. { if (PdfPatternsPage.ContainsKey(pattern.PdfPageN)) { PdfPatternsPage[pattern.PdfPageN].Add(pattern); } else { PdfPatternsPage[pattern.PdfPageN] = new List <PdfTagPattern>() { pattern } }; } foreach (var page in pdf.PdfUnstructuredPages) { ExtractFromRectangles(page.WordGroups, result.MetadataType, hierarchySet, result, page.PdfPageN); ExtractFromRectangles(page.Lines, result.MetadataType, hierarchySet, result, page.PdfPageN, "LinesInfos"); ExtractFromText(result.MetadataType, result, page, hierarchySet); ExtractFromColorFontText(page.ColorFontWordGroups, result.MetadataType, hierarchySet, result, page.PdfPageN); } result.Converters = _Converters; result.GetMetadata(); return(result); }
/// <summary> /// Ejecuata la extracción basada en limites /// textuales. /// </summary> /// <param name="metadataType">Tipo de la clase que implementa IMetadata.</param> /// <param name="result">Resultado de extracción.</param> /// <param name="page">PdfUnstructuredPage del doc. pdf.</param> /// <param name="hierarchySet">Catálogo de jerarquías.</param> private void ExtractFromText(Type metadataType, PdfTagExtractionResult result, PdfUnstructuredPage page, IHierarchySet hierarchySet) { foreach (var pattern in PdfPatterns) { if (pattern.PdfPageN == page.PdfPageN || pattern.IsLastPage) // Comprobamos que los patrones realicen la extracción sobre la página que les corresponde. // Se comprueba la última página porque en algunos documentos viene primero los albaranes y al final la factura. { if (pattern.SourceTypeName == "PdfTextInfos") { foreach (Match match in Regex.Matches(page.PdfText, pattern.RegexPattern)) { PropertyInfo pInf = metadataType.GetProperty(pattern.MetadataItemName); if (pInf.PropertyType == typeof(string)) { result.AddResult(pattern, match.Value); } else { dynamic converter = null; if (_Converters.ContainsKey(pInf.PropertyType)) { converter = _Converters[pInf.PropertyType]; } else { ITextParserHierarchy parserHierarchy = hierarchySet.GetParserHierarchy(pInf); converter = parserHierarchy.GetConverter(pInf.PropertyType); if (converter == null) { Type converterGenType = typeof(Converter <>).MakeGenericType(pInf.PropertyType); converter = Activator.CreateInstance(converterGenType); } } object pValue = converter.Convert(match.Value); result.AddResult(pattern, pValue); } } } } } }
/// <summary> /// Ejecuata la extracción basada en limites /// textuales. /// </summary> /// <param name="metadataType">Tipo de la clase que implementa IMetadata.</param> /// <param name="result">Resultado de extracción.</param> /// <param name="page">PdfUnstructuredPage del doc. pdf.</param> private void ExtractFromText(Type metadataType, PdfTagExtractionResult result, PdfUnstructuredPage page, IHierarchySet hierarchySet) { foreach (var pattern in PdfPatterns) { if (pattern.SourceTypeName == "PdfTextInfos") { foreach (Match match in Regex.Matches(page.PdfText, pattern.RegexPattern)) { PropertyInfo pInf = metadataType.GetProperty(pattern.MetadataItemName); if (pInf.PropertyType == typeof(string)) { result.AddResult(pattern, match.Value); } else { dynamic converter = null; if (_Converters.ContainsKey(pInf.PropertyType)) { converter = _Converters[pInf.PropertyType]; } else { ITextParserHierarchy parserHierarchy = hierarchySet.GetParserHierarchy(pInf); converter = parserHierarchy.GetConverter(pInf.PropertyType); if (converter == null) { Type converterGenType = typeof(Converter <>).MakeGenericType(pInf.PropertyType); converter = Activator.CreateInstance(converterGenType); } } object pValue = converter.Convert(match.Value); result.AddResult(pattern, pValue); } } } } }
/// <summary> /// Ejecuta el proceso de extracción de metadatos /// en base a los patrones almacenados. /// </summary> /// <param name="pdfDocRectangles">rectángulos del pdf doc.</param> /// <param name="metadataType">Implementa IMetadata.</param> /// <param name="hierarchySet">Catálogo de jerarquías.</param> /// <param name="result">Resultados.</param> /// <param name="sourceTypeName">Nombre de la fuente.</param> private void ExtractFromRectangles(List <PdfTextRectangle> pdfDocRectangles, Type metadataType, IHierarchySet hierarchySet, PdfTagExtractionResult result, string sourceTypeName = "WordGroupsInfos") { foreach (var pdfDocRectangle in pdfDocRectangles) { foreach (var pattern in PdfPatterns) { if (pattern.SourceTypeName == sourceTypeName) { if (IsAlmostSameArea(pdfDocRectangle, pattern.PdfRectangle)) { string textInput = pdfDocRectangle.Text; PropertyInfo pInf = metadataType.GetProperty(pattern.MetadataItemName); ITextParserHierarchy parserHierarchy = hierarchySet.GetParserHierarchy(pInf); if (pInf.PropertyType == typeof(string)) { parserHierarchy.SetParserRegexPattern(0, pattern.RegexPattern); } dynamic converter = parserHierarchy.GetConverter(pattern.RegexPattern); MatchCollection matches = Regex.Matches(pdfDocRectangle.Text, pattern.RegexPattern); string val = (pattern.Position < matches.Count) ? matches[pattern.Position].Value : null; object pValue = null; if (val != null && converter != null) { pValue = converter.Convert(val); } if (pValue != null && !PdfCompare.IsZeroNumeric(pValue)) { result.AddResult(pattern, pValue); if (!_Converters.ContainsKey(pInf.PropertyType)) { _Converters.Add(pInf.PropertyType, converter); } } } } } } }
/// <summary> /// Ejecuta el proceso de extracción de metadatos /// a partir de los patrones almacenados. /// En este caso los metadatos deben coincidir en 4 propiedades: /// FontType, FontSize, ColorFill, ColorStroke. /// En caso de acierto, se compara la RegEx. /// </summary> /// <param name="pdfDocTextStrings">Los textStrings obtenidos con el texto y las 4 propiedades.</param> /// <param name="metadataType">Implementa IMetadata. Sirve para averiguar el tipo de dato. Ejemplos: int, string, etc.</param> /// <param name="hierarchySet">Catálogo de jerarquías.</param> /// <param name="result">Guarda los resultados obtenidos con este método de extracción.</param> private void ExtractFromTextStrings(List <PdfClownTextString> pdfDocTextStrings, Type metadataType, IHierarchySet hierarchySet, PdfTagExtractionResult result) { foreach (var textString in pdfDocTextStrings) { foreach (var pattern in PdfPatterns) { if (pattern.SourceTypeName == "TextStringInfos") { if (textString.ColorFill.BaseDataObject.ToString().Equals(pattern.ColorFill) && textString.ColorStroke.BaseDataObject.ToString().Equals(pattern.ColorStroke) && textString.FontSize.ToString().Equals(pattern.FontSize) && textString.FontType.Name.Equals(pattern.FontType) && textString.Type.Equals(pattern.TsType)) { if (pattern.TsType.Equals("NA") || (pattern.TsType.Equals("X") && textString.Rectangle != null && pattern.TsCoordinate.Equals(textString.Rectangle.Value.X.ToString())) || (pattern.TsType.Equals("Y") && textString.Rectangle != null && pattern.TsCoordinate.Equals(textString.Rectangle.Value.Y.ToString()))) { // Cumple los 4 parámetros del textString // por lo que debemos comprobar el contenido // (convirtiendo el dato primero a un tipo comparable) string textInput = textString.Text; PropertyInfo pInf = metadataType.GetProperty(pattern.MetadataItemName); ITextParserHierarchy parserHierarchy = hierarchySet.GetParserHierarchy(pInf); if (pInf.PropertyType == typeof(string)) { parserHierarchy.SetParserRegexPattern(0, pattern.RegexPattern); } dynamic converter = parserHierarchy.GetConverter(pattern.RegexPattern); MatchCollection matches = Regex.Matches(textString.Text, pattern.RegexPattern); string val = (pattern.Position < matches.Count) ? matches[pattern.Position].Value : null; object pValue = null; if (val != null && converter != null) { pValue = converter.Convert(val); } if (pValue != null && !PdfCompare.IsZeroNumeric(pValue)) { result.AddResult(pattern, pValue); if (!_Converters.ContainsKey(pInf.PropertyType)) { _Converters.Add(pInf.PropertyType, converter); } } } } } } } }
/// <summary> /// Ejecuta el proceso de extracción de metadatos /// en base a los patrones almacenados. /// </summary> /// <param name="pdfDocColorFontText">Rectángulos del pdf doc con color, tamaño y nombre de fuente.</param> /// <param name="metadataType">Implementa IMetadata.</param> /// <param name="hierarchySet">Catálogo de jerarquías.</param> /// <param name="result">Resultados.</param> /// <param name="pageNumber">Número de la página sobre la que se realiza la extracción.</param> private void ExtractFromColorFontText(List <PdfColorFontTextRectangle> pdfDocColorFontText, Type metadataType, IHierarchySet hierarchySet, PdfTagExtractionResult result, int pageNumber) { string sourceTypeName = "ColorFontWordGroupsInfos"; foreach (var pdfDocColorFontWord in pdfDocColorFontText) { foreach (var pattern in PdfPatterns) { if (pattern.PdfPageN == pageNumber || pattern.IsLastPage) // Comprobamos que los patrones realicen la extracción sobre la página que les corresponde. // Se comprueba la última página porque en algunos documentos viene primero los albaranes y al final la factura. { if (pattern.SourceTypeName == sourceTypeName) { if (pdfDocColorFontWord.FillColor == pattern.FillColor && pdfDocColorFontWord.StrokeColor == pattern.StrokeColor && pdfDocColorFontWord.FontName == pattern.FontName && pdfDocColorFontWord.FontSize.ToString() == pattern.FontSize ) // Comprobamos que tienen el mismo color, tamaño y nombre de fuente. // No comprobamos el CFType porque cuando llega aquí, pdfDocColorFontWord no tiene un CFType asignado aún. { if (pattern.CFType.Equals("NA") || (pattern.CFType.Equals("X") && (pattern.PdfRectangle.Llx.Equals(pdfDocColorFontWord.Llx) || pattern.PdfRectangle.Urx.Equals(pdfDocColorFontWord.Urx))) || (pattern.CFType.Equals("Y") && (pattern.PdfRectangle.Lly.Equals(pdfDocColorFontWord.Lly) || pattern.PdfRectangle.Ury.Equals(pdfDocColorFontWord.Ury)))) { string textInput = pdfDocColorFontWord.Text; PropertyInfo pInf = metadataType.GetProperty(pattern.MetadataItemName); ITextParserHierarchy parserHierarchy = hierarchySet.GetParserHierarchy(pInf); if (pInf.PropertyType == typeof(string)) { parserHierarchy.SetParserRegexPattern(0, pattern.RegexPattern); } dynamic converter = parserHierarchy.GetConverter(pattern.RegexPattern); MatchCollection matches = Regex.Matches(pdfDocColorFontWord.Text, pattern.RegexPattern); string val = (pattern.Position < matches.Count) ? matches[pattern.Position].Value : null; object pValue = null; if (val != null && converter != null) { pValue = converter.Convert(val); } if (pValue != null && !PdfCompare.IsZeroNumeric(pValue)) { result.AddResult(pattern, pValue); if (!_Converters.ContainsKey(pInf.PropertyType)) { _Converters.Add(pInf.PropertyType, converter); } } } } } } } } }
/// <summary> /// Ejecuta el proceso de extracción de metadatos /// en base a los patrones almacenados. /// </summary> /// <param name="pdfDocRectangles">rectángulos del pdf doc.</param> /// <param name="metadataType">Implementa IMetadata.</param> /// <param name="hierarchySet">Catálogo de jerarquías.</param> /// <param name="result">Resultados.</param> /// <param name="pageNumber">Número de la página sobre la que se realiza la extracción.</param> /// <param name="sourceTypeName">Nombre de la fuente.</param> private void ExtractFromRectangles(List <PdfTextRectangle> pdfDocRectangles, Type metadataType, IHierarchySet hierarchySet, PdfTagExtractionResult result, int pageNumber, string sourceTypeName = "WordGroupsInfos") { foreach (var pdfDocRectangle in pdfDocRectangles) { foreach (var pattern in PdfPatterns) { if (pattern.PdfPageN == pageNumber || pattern.IsLastPage) // Comprobamos que los patrones realicen la extracción sobre la página que les corresponde. // Se comprueba la última página porque en algunos documentos viene primero los albaranes y al final la factura. { if (pattern.SourceTypeName == sourceTypeName) { if (IsAlmostSameArea(pdfDocRectangle, pattern.PdfRectangle)) { string textInput = pdfDocRectangle.Text; PropertyInfo pInf = metadataType.GetProperty(pattern.MetadataItemName); ITextParserHierarchy parserHierarchy = hierarchySet.GetParserHierarchy(pInf); if (pInf.PropertyType == typeof(string)) { parserHierarchy.SetParserRegexPattern(0, pattern.RegexPattern); } dynamic converter = parserHierarchy.GetConverter(pattern.RegexPattern); MatchCollection matches = Regex.Matches(pdfDocRectangle.Text, pattern.RegexPattern); int p = pattern.Position; int m = matches.Count; string val = (pattern.Position < matches.Count) ? matches[pattern.Position].Value : null; object pValue = null; if (val != null && converter != null) { pValue = converter.Convert(val); } if (pValue != null && !PdfCompare.IsZeroNumeric(pValue)) { result.AddResult(pattern, pValue); if (!_Converters.ContainsKey(pInf.PropertyType)) { _Converters.Add(pInf.PropertyType, converter); } } } } } } } }