@nelsonrc/nrc-phoenix-xml
v1.0.3
Published
A declarative XML summarizer with formatting logic for Angular apps and automation workflows.
Maintainers
Readme
nrc-phoenix-xml
Advanced XML Utilities for TypeScript
A powerful and modular library for parsing, validating, and summarizing XML data.
🚀 Features
- XML Parsing & Validation with XSD support
- Data Summarization with configurable aggregation methods
- Data Summarization of same field with different measures
- Modular and Scalable Architecture
- Localization Support (e.g., currency & percentage formatting)
- Built-in Error Handling and Debugging
📦 Installation
Install via npm:
npm install nrc-phoenix-xml📘 Documentation
Full API reference and usage examples are available at:
👉 https://nelsonrc.github.io/nrc-phoenix-xml/
🔹 parseXmlSummary(summaryStr: string): IXmlSummary
Parses a summary string into a structured summary configuration.
summaryStr: Comma-separated configuration string- Returns:
IXmlSummaryobject - Throws: Error if string is malformed
🔹 Code
import { parseXmlSummary } from "nrc-phoenix-xml"
const summary = "Item,1,Category:Group,Price:Total Price:1,Qty:Count:3"
const result = parseXmlSummary(summary)
console.log(result)🔹 Output
{
"targetNode": "Item",
"orientation": 1,
"groupingField": "Category",
"groupingDisplayName": "Group",
"fields": [
{ "name": "Price", "displayName": "Total Price", "measure": 1 },
{ "name": "Qty", "displayName": "Count", "measure": 3 }
]
}🔹 parseFormatOptions(optionsStr: string): IXmlSummaryFormatOptions
Parses a compact options string into a formatting config object.
optionsStr: Key-value string (e.g.rd=2,cu=USD)- Returns:
IXmlSummaryFormatOptionsobject
🔹 Code
import { parseFormatOptions } from "nrc-phoenix-xml"
const config = "rd=2,cu=USD,sc=1,as=1,tm=0,sr=1,pf=Avg%|Rate%,if=Qty|Count"
const options = parseFormatOptions(config)
console.log(options)🔹 Output
{
"roundDecimals": 2,
"currency": "USD",
"showCurrencySymbol": true,
"asJson": true,
"treatMissingAsZero": false,
"sortResults": true,
"percentageFields": ["Avg%", "Rate%"],
"integerFields": ["Qty", "Count"]
}🔹 parseSpecAndOptions(input: string, delimiter = ';'): { xmlSummaryStr, formatingOpts }
Parses a combined string of summary + formatting into separate config objects.
input:"entry,1,*:Summary,total:Label:1;rd=2"delimiter: Optional separator (default:;)- Returns:
{ xmlSummaryStr: IXmlSummary, formatingOpts: IXmlSummaryFormatOptions } - Throws: Error if either part is missing
🔹 Code
import { parseSpecAndOptions } from "nrc-phoenix-xml"
const input = "Item,2,Dept:Totals,Price:Price:1,Qty:Total Qty:3;rd=2,cu=USD,sc=1,as=1"
const { xmlSummaryStr, formatingOpts } = parseSpecAndOptions(input)
console.log({ xmlSummaryStr, formatingOpts })🔹 Output
{
"xmlSummaryStr": {
"targetNode": "Item",
"orientation": 2,
"groupingField": "Dept",
"groupingDisplayName": "Totals",
"fields": [
{ "name": "Price", "displayName": "Price", "measure": 1 },
{ "name": "Qty", "displayName": "Total Qty", "measure": 3 }
]
},
"formatingOpts": {
"roundDecimals": 2,
"currency": "USD",
"showCurrencySymbol": true,
"asJson": true
}
}🔹 getSummaryFromXml(xml: string, spec: IXmlSummary, debug?: boolean, format?: IXmlSummaryFormatOptions): SummaryDictionary | string
Generates an aggregated summary from raw XML, given a structured spec.
xml: Raw XML stringspec: Parsed summary definitiondebug: Optional diagnostic outputformat: Formatting preferences- Returns: Object or JSON string based on
asJsonflag
🔹 Code
import { XmlSummarizer, parseXmlSummary, parseFormatOptions } from "nrc-phoenix-xml"
const xml = `<items>
<item><category>A</category><price>10.5</price><qty>2</qty></item>
<item><category>A</category><price>5.0</price><qty>1</qty></item>
<item><category>B</category><price>12.0</price><qty>3</qty></item>
</items>`
const summarySpec = parseXmlSummary("item,1,category:Category,price:Total Price:1,qty:Count:3")
const formatOptions = parseFormatOptions("rd=2,cu=USD,sc=1,as=1")
const result = XmlSummarizer.getSummaryFromXml(xml, summarySpec, false, formatOptions)
console.log(result)🔹 Output
{
"Category": {
"A": [
{ "name": "Total Price", "value": "$15.50" },
{ "name": "Count", "value": 3 }
],
"B": [
{ "name": "Total Price", "value": "$12.00" },
{ "name": "Count", "value": 3 }
]
}
}🔹 processXmlSummary(xml: string, summaryStr: string, debug?: boolean, format?: IXmlSummaryFormatOptions): SummaryDictionary | string
Simplified method that parses and summarizes XML data in one step.
xml: XML stringsummaryStr: Configuration stringdebug: Show debug logs (optional)format: Output options- Returns: Summary data grouped by field or JSON string
🔹 Code
import { XmlSummarizer } from "nrc-phoenix-xml"
const xmlData = `<sales>
<entry><region>North</region><total>1250.50</total></entry>
<entry><region>North</region><total>470.25</total></entry>
<entry><region>South</region><total>815.75</total></entry>
</sales>`
const summaryStr = "entry,1,region:Region,total:Total Sales:1"
const format = {
roundDecimals: 2,
currency: "USD",
showCurrencySymbol: true,
asJson: true,
sortResults: true
}
const result = XmlSummarizer.processXmlSummary(xmlData, summaryStr, false, format)
console.log(result)🔹 Output
{
"Region": {
"North": [
{ "name": "Total Sales", "value": "$1,720.75" }
],
"South": [
{ "name": "Total Sales", "value": "$815.75" }
]
}
}📝 Summary String Format
The summaryString parameter follows a comma-separated structure, defining XML elements and their aggregation behavior.
📌 Format:
elementName,summaryOrientation,groupingField,groupingDisplayName,attribute1:Label1:aggregationType,attribute2:Label2:aggregationType🔹 Explanation
elementName→ Target parent XML element for summarization.summaryOrientation→ Reserved for future versions to define how summaries are organized (currently unused).groupingField→ Defines the field used for grouping. If"*", there is no grouping.groupingDisplayName→ Specifies the key returned in the result, representing thegroupingField. IfgroupingField == "*", this acts as the general summary name.attribute:Label:aggregationMeasure→ Specifies attributes, labels, and aggregation methods.
🔹 Example Summary String
transaction,1,portfolio_type:Portfolio type,acquisition_value:Acquisition value:1,market_value:Market value:1transaction→ XML element being processed.1→ summaryOrientation, reserved for future use.portfolio_type→ Used for grouping (e.g.,"A"and"B").Portfolio type→ The label returned in the result representingportfolio_type.acquisition_value→ Summarized field representing acquisition value.Acquisition value→ Label assigned toacquisition_valuein the summary result.market_value→ Summarized field representing market value.Market value→ Label assigned tomarket_valuein the summary result.
🔹 Expected Output
{
"Portfolio type": {
"A": [
{ "name": "Acquisition value", "value": "$1,000.75" },
{ "name": "Market value", "value": "$1,050.50" }
],
"B": [
{ "name": "Acquisition value", "value": "$500.50" },
{ "name": "Market value", "value": "$520.80" }
]
}
}📊 Aggregation Measures
| Code | Name | Description |
|----------|----------------------|--------------------------------------------------|
| 1 | Sum | Adds all values together |
| 2 | Average | Calculates the mean of values |
| 3 | Count | Counts the number of occurrences |
| 4 | Min | Finds the smallest value |
| 5 | Max | Finds the largest value |
| 6 | Standard Deviation | Measures how spread out the values are |
🧩 Format Options Reference
| Key | Option | Type | Description |
|--------:|-------------------------|--------------|-------------------------------------------------------------|
| rd | roundDecimals | number | Decimal precision to round summarized values |
| cu | currency | string | ISO currency code (e.g., USD, EUR) |
| sc | showCurrencySymbol | boolean | Show currency symbol (1 = true, 0 = false) |
| as | asJson | boolean | Output as JSON (1 = true) or string |
| tm | treatMissingAsZero | boolean | Handle empty fields as zero when aggregating |
| sr | sortResults | boolean | Sort summary output by display name |
| pf | percentageFields | string[] | List of fields treated as percentages (pipe-separated) |
| if | integerFields | string[] | List of fields treated as whole numbers (pipe-separated) |
🛠 Tools & Scripts
The tools/ directory contains handy shell scripts that simplify common tasks such as initializing the repo, generating documentation, and deploying updates to GitHub Pages.
🔹 deploy-docs.sh
Generates and deploys the API documentation to the gh-pages branch.
./tools/deploy-docs.sh- Uses
typedocandtypedoc.jsonconfig - Automatically switches branches and pushes updates
- Safe for manual and CI/CD usage
🔹 commit-and-deploy.sh
Commits staged changes and redeploys documentation in one command.
./tools/commit-and-deploy.sh "Update docs and push latest changes"- Stages and commits current updates
- Calls deploy-docs.sh afterward
- Useful for quick publishing cycles
🔹 init-repo.sh
./tools/init-repo.sh🧰 Usage Tips
chmod +x ./tools/*.shThen you can run them directly, or include them in your package.json:
"scripts": {
"docs": "typedoc",
"docs:deploy": "./tools/deploy-docs.sh",
"init": "./tools/init-repo.sh"
}💡 Keep these scripts modular and version-controlled to support reproducible builds and deployments.
📦 Tests
Unit and functional tests are located in the tests/ directory to ensure correctness, scalability, and resilience of core features.
🧪 Running All Tests
npm run testFor watch mode during development:
npx jest --watch▶️ Run Specific Test File
npx jest tests/XmlSummarizer.test.ts📂 Structure
tests/
├── XmlSummarizer.test.ts # Tests for summary computation logic
├── parseXmlSummary.test.ts # Tests for summary string parsing
├── parseFormatOptions.test.ts # Tests for format configuration parsing
├── parseSpecAndOptions.test.ts # Tests for combined parsing Each test uses Jest and follows the .test.ts naming convention for discoverability.
📊 Optional: Code Coverage
npx jest --coverageReports will appear in the coverage/ folder.
💡 Tip: Grouping-related tests can live under tests/groups/, while shared mocks can go in tests/utils/.
🏗️ Contribution Guidelines
🔹 How to Contribute
We welcome contributions to improve nrc-phoenix-xml! To contribute:
Fork the repository:
git clone https://github.com/nelsonrc/nrc-phoenix-xml.gitInstall dependencies:
npm installCreate a feature branch:
git checkout -b feature/new-functionalitySubmit a Pull Request 🚀
📜 License
This project is licensed under the MIT License. See LICENSE for details.
📞 Support & Issues
For issues or support, visit GitHub Issues.
