Replace library for cdrc xml with github.com/antchfx/xmlquery

This commit is contained in:
TeoV
2018-09-25 09:07:01 -04:00
committed by Dan Christian Bogos
parent a07e4b1e39
commit 5c240017fd
4 changed files with 33 additions and 41 deletions

View File

@@ -26,7 +26,7 @@ import (
"strings"
"time"
"github.com/beevik/etree"
"github.com/antchfx/xmlquery"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/engine"
"github.com/cgrates/cgrates/utils"
@@ -34,17 +34,18 @@ import (
// getElementText will process the node to extract the elementName's text out of it (only first one found)
// returns utils.ErrNotFound if the element is not found in the node
func elementText(xmlElement *etree.Element, elmntPath string) (string, error) {
elmnt := xmlElement.FindElement(elmntPath)
func elementText(xmlElement *xmlquery.Node, elmntPath string) (string, error) {
elmnt := xmlquery.FindOne(xmlElement, elmntPath)
if elmnt == nil {
return "", utils.ErrNotFound
}
return elmnt.Text(), nil
return elmnt.InnerText(), nil
}
// handlerUsageDiff will calculate the usage as difference between timeEnd and timeStart
// Expects the 2 arguments in template separated by |
func handlerSubstractUsage(xmlElement *etree.Element, argsTpl config.RSRParsers, cdrPath utils.HierarchyPath, timezone string) (time.Duration, error) {
func handlerSubstractUsage(xmlElement *xmlquery.Node, argsTpl config.RSRParsers, cdrPath utils.HierarchyPath, timezone string) (time.Duration, error) {
var argsStr string
for _, rsrArg := range argsTpl {
if rsrArg.Rules == utils.HandlerArgSep {
@@ -79,21 +80,20 @@ func handlerSubstractUsage(xmlElement *etree.Element, argsTpl config.RSRParsers,
func NewXMLRecordsProcessor(recordsReader io.Reader, cdrPath utils.HierarchyPath, timezone string,
httpSkipTlsCheck bool, cdrcCfgs []*config.CdrcConfig, filterS *engine.FilterS) (*XMLRecordsProcessor, error) {
xmlDocument := etree.NewDocument() // create new document
xmlDocument.ReadSettings.CharsetReader = func(label string, input io.Reader) (io.Reader, error) { // fix for enconding != UTF-8
return input, nil
}
if _, err := xmlDocument.ReadFrom(recordsReader); err != nil { // read file and build xml document
//create doc
doc, err := xmlquery.Parse(recordsReader)
if err != nil {
return nil, err
}
xmlProc := &XMLRecordsProcessor{cdrPath: cdrPath, timezone: timezone,
httpSkipTlsCheck: httpSkipTlsCheck, cdrcCfgs: cdrcCfgs, filterS: filterS}
xmlProc.cdrXmlElmts = xmlDocument.Root().FindElements(cdrPath.AsString("/", true))
xmlProc.cdrXmlElmts = xmlquery.Find(doc, cdrPath.AsString("/", true))
return xmlProc, nil
}
type XMLRecordsProcessor struct {
cdrXmlElmts []*etree.Element // result of splitting the XML doc into CDR elements
cdrXmlElmts []*xmlquery.Node // result of splitting the XML doc into CDR elements
procItems int // current number of processed records from file
cdrPath utils.HierarchyPath // path towards one CDR element
timezone string
@@ -137,7 +137,7 @@ func (xmlProc *XMLRecordsProcessor) ProcessNextRecord() (cdrs []*engine.CDR, err
return cdrs, nil
}
func (xmlProc *XMLRecordsProcessor) recordToCDR(xmlEntity *etree.Element, cdrcCfg *config.CdrcConfig, tenant string) (*engine.CDR, error) {
func (xmlProc *XMLRecordsProcessor) recordToCDR(xmlEntity *xmlquery.Node, cdrcCfg *config.CdrcConfig, tenant string) (*engine.CDR, error) {
cdr := &engine.CDR{OriginHost: "0.0.0.0", Source: cdrcCfg.CdrSourceId, ExtraFields: make(map[string]string), Cost: -1}
var lazyHttpFields []*config.FCTemplate
var err error
@@ -206,14 +206,14 @@ func (xmlProc *XMLRecordsProcessor) recordToCDR(xmlEntity *etree.Element, cdrcCf
}
// newXmlProvider constructs a DataProvider
func newXmlProvider(req *etree.Element, cdrPath utils.HierarchyPath) (dP config.DataProvider) {
func newXmlProvider(req *xmlquery.Node, cdrPath utils.HierarchyPath) (dP config.DataProvider) {
dP = &xmlProvider{req: req, cdrPath: cdrPath, cache: config.NewNavigableMap(nil)}
return
}
// xmlProvider implements engine.DataProvider so we can pass it to filters
type xmlProvider struct {
req *etree.Element
req *xmlquery.Node
cdrPath utils.HierarchyPath //used to compute relative path
cache *config.NavigableMap
}

View File

@@ -19,13 +19,13 @@ package cdrc
import (
"bytes"
"io"
"path"
"reflect"
"strings"
"testing"
"time"
"github.com/beevik/etree"
"github.com/antchfx/xmlquery"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/engine"
"github.com/cgrates/cgrates/utils"
@@ -167,15 +167,11 @@ var cdrXmlBroadsoft = `<?xml version="1.0" encoding="ISO-8859-1"?>
</broadWorksCDR>`
func TestXMLElementText(t *testing.T) {
doc := etree.NewDocument()
doc.ReadSettings.CharsetReader = func(label string, input io.Reader) (io.Reader, error) {
return input, nil
}
if err := doc.ReadFromBytes([]byte(cdrXmlBroadsoft)); err != nil {
doc, err := xmlquery.Parse(strings.NewReader(cdrXmlBroadsoft))
if err != nil {
t.Error(err)
}
cdrs := doc.FindElements(path.Join("/broadWorksCDR/cdrData/"))
cdrs := xmlquery.Find(doc, path.Join("/broadWorksCDR/cdrData/"))
cdrWithoutUserNr := cdrs[0]
if _, err := elementText(cdrWithoutUserNr, "basicModule/userNumber"); err != utils.ErrNotFound {
t.Error(err)
@@ -194,15 +190,12 @@ func TestXMLElementText(t *testing.T) {
}
func TestXMLHandlerSubstractUsage(t *testing.T) {
doc := etree.NewDocument()
doc.ReadSettings.CharsetReader = func(label string, input io.Reader) (io.Reader, error) {
return input, nil
}
if err := doc.ReadFromBytes([]byte(cdrXmlBroadsoft)); err != nil {
doc, err := xmlquery.Parse(strings.NewReader(cdrXmlBroadsoft))
if err != nil {
t.Error(err)
}
cdrs := doc.FindElements(path.Join("/broadWorksCDR/cdrData/"))
cdrs := xmlquery.Find(doc, path.Join("/broadWorksCDR/cdrData/"))
cdrWithUsage := cdrs[1]
if usage, err := handlerSubstractUsage(cdrWithUsage,
config.NewRSRParsersMustCompile("~broadWorksCDR.cdrData.basicModule.releaseTime;|;~broadWorksCDR.cdrData.basicModule.answerTime", true),
@@ -516,12 +509,12 @@ var xmlContent = `<?xml version="1.0" encoding="UTF-8"?>
`
func TestXMLElementText3(t *testing.T) {
doc := etree.NewDocument()
if err := doc.ReadFromString(xmlContent); err != nil {
doc, err := xmlquery.Parse(strings.NewReader(xmlContent))
if err != nil {
t.Error(err)
}
hPath2 := utils.ParseHierarchyPath("File.CDRs.Call", "")
cdrs := doc.Root().FindElements(hPath2.AsString("/", true))
cdrs := xmlquery.Find(doc, hPath2.AsString("/", true))
if len(cdrs) != 3 {
t.Errorf("Expecting: 3, received: %+v", len(cdrs))
}
@@ -530,11 +523,7 @@ func TestXMLElementText3(t *testing.T) {
t.Error(err)
}
absolutePath := utils.ParseHierarchyPath("File.CDRs.Call.SignalingInfo.PChargingVector.icidvalue", "")
hPath := utils.ParseHierarchyPath(cdrs[1].GetPath(), "")
relPath := utils.HierarchyPath(absolutePath[len(hPath):]) // Need relative path to the xmlElmnt
if val, err := elementText(cdrs[1], relPath.AsString("/", false)); err != nil {
if val, err := elementText(cdrs[1], "SignalingInfo/PChargingVector/icidvalue"); err != nil {
t.Error(err)
} else if val != "46d7974398c2671016afccc3f2c428c7" {
t.Errorf("Expecting: 46d7974398c2671016afccc3f2c428c7, received: %s", val)

6
glide.lock generated
View File

@@ -105,6 +105,8 @@ imports:
- internal/scram
- name: github.com/dlintw/goconf
version: dcc070983490608a14480e3bf943bad464785df5
- name: github.com/beevik/etree
version: 90dafc1e1f114dfb9576218bb43c03fb854d1b34
- name: github.com/antchfx/xmlquery
version: 07935b1c0f2e6f0efa02c98cd70e223d70218955
- name: github.com/antchfx/xpath
version: 3de91f3991a1af6e495d49c9218318b5544b20e3
testImports: []

View File

@@ -41,4 +41,5 @@ import:
- package: github.com/cgrates/radigo
- package: github.com/cgrates/ltcache
- package: github.com/dlintw/goconf
- package: github.com/beevik/etree
- package: github.com/antchfx/xmlquery
- package: github.com/antchfx/xpath