Skip to content

Fix: Citavi XML importer now preserves citation keys (#14658)#15257

Merged
Siedlerchr merged 4 commits into
JabRef:mainfrom
JunWang222:fix/issue-14658-citavi-citation-key
Mar 3, 2026
Merged

Fix: Citavi XML importer now preserves citation keys (#14658)#15257
Siedlerchr merged 4 commits into
JabRef:mainfrom
JunWang222:fix/issue-14658-citavi-citation-key

Conversation

@JunWang222

@JunWang222 JunWang222 commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Related issues and pull requests

Closes #14658

PR Description

Previously, citation keys defined in Citavi (stored as in the XML) were silently discarded during import, leaving all entries with empty citation keys.

Now the importer reads the element and sets it on the imported BibEntry (with whitespace stripped, as BibTeX does not allow spaces in keys).

Steps to test

UI test: Import the file we added jabref/jablib/src/test/resources/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest4.ctv6bak
Behavior before the fix: The citiation key is empty
Screenshot 2026-03-03 at 12 23 53 AM

Behavior after the fix: The citation key is present
Screenshot 2026-03-03 at 12 46 07 AM

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • I manually tested my changes in running JabRef (always required)
  • I added JUnit tests for changes (if applicable)
  • I added screenshots in the PR description (if change is visible to the user)
  • I added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
  • I described the change in CHANGELOG.md in a way that can be understood by the average user (if change is visible to the user)
  • I checked the user documentation for up to dateness and submitted a pull request to our user documentation repository

@JunWang222 JunWang222 force-pushed the fix/issue-14658-citavi-citation-key branch from 322ef30 to 84d7a00 Compare March 3, 2026 06:02
@github-actions github-actions Bot mentioned this pull request Mar 3, 2026
Previously, citation keys defined in Citavi (stored as <CitationKey> in
the XML) were silently discarded during import, leaving all entries with
empty citation keys.

Now the importer reads the <CitationKey> element and sets it on the
imported BibEntry (with whitespace stripped, as BibTeX does not allow
spaces in keys).
@JunWang222 JunWang222 force-pushed the fix/issue-14658-citavi-citation-key branch from 84d7a00 to 9fa39b5 Compare March 3, 2026 06:09
@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: no-bot-comments labels Mar 3, 2026
@JunWang222 JunWang222 marked this pull request as ready for review March 3, 2026 06:18
@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Citavi XML importer now preserves citation keys from XML

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Citavi XML importer now reads and preserves citation keys from XML
• Citation keys are stripped of whitespace to comply with BibTeX format
• Empty or blank citation keys are ignored during import
• Added comprehensive unit tests for citation key handling
Diagram
flowchart LR
  A["Citavi XML<br/>CitationKey element"] -->|"Read element"| B["CitaviXmlImporter<br/>parseReference"]
  B -->|"Extract & strip<br/>whitespace"| C["Reference record<br/>citationKey field"]
  C -->|"Set on entry"| D["BibEntry<br/>with citation key"]
Loading

Grey Divider

File Changes

1. jablib/src/main/java/org/jabref/logic/importer/fileformat/CitaviXmlImporter.java 🐞 Bug fix +8/-1

Extract and apply citation keys from XML

• Added citationKey variable to capture the CitationKey XML element
• Added case handler for "CitationKey" element in the switch statement
• Updated Reference constructor call to include the citationKey parameter
• Added logic in setEntryFieldsFromReference to set citation key on BibEntry with whitespace
 stripping

jablib/src/main/java/org/jabref/logic/importer/fileformat/CitaviXmlImporter.java


2. jablib/src/main/java/org/jabref/logic/importer/fileformat/citavi/Reference.java ✨ Enhancement +2/-1

Add citation key field to record

• Added citationKey field to the Reference record

jablib/src/main/java/org/jabref/logic/importer/fileformat/citavi/Reference.java


3. jablib/src/test/java/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest.java 🧪 Tests +89/-0

Add comprehensive citation key import tests

• Added imports for test utilities and BibEntry
• Added three new test methods: importPreservesCitationKey, importIgnoresEmptyCitationKey,
 importStripsWhitespaceFromCitationKey
• Added helper method importFromXml to create test ctv6bak files from XML strings
• Tests verify citation key preservation, empty key handling, and whitespace stripping

jablib/src/test/java/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest.java


View more (5)
4. jablib/src/test/resources/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest3.bib 🧪 Tests +20/-20

Update test fixture with citation keys

• Updated multiple BibTeX entries to include citation keys that were previously empty
• Citation keys added: Allan2003, Ame08, And05, Baw01, BrGe, Bru99, Cox08, EiLoSp04, Gou02, Har97,
 HuWaLe98, Joi05, McLu00, BrFrSt03, Rob05, Ros02, Rum08, SmChMa05, SnCo97, UrThSp05

jablib/src/test/resources/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest3.bib


5. jablib/src/test/resources/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest4.bib 🧪 Tests +1/-1

Update test fixture citation key

• Updated single entry to include citation key "Har97" instead of empty key

jablib/src/test/resources/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest4.bib


6. jablib/src/test/resources/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest5.bib 🧪 Tests +19/-0

Add new test fixture for citation key scenarios

• New test fixture file with four entries demonstrating different citation key scenarios
• Includes entries with simple keys, keys with spaces, no keys, and blank keys

jablib/src/test/resources/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest5.bib


7. jablib/src/test/resources/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest5.ctv6bak 🧪 Tests +0/-0

Add binary test fixture for citation keys

• New binary test fixture file (ZIP archive containing XML)
• Contains test data for citation key import scenarios

jablib/src/test/resources/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest5.ctv6bak


8. CHANGELOG.md 📝 Documentation +1/-0

Document citation key preservation fix

• Added entry documenting the fix for Citavi XML importer citation key preservation
• References issue #14658

CHANGELOG.md


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Test uses orElse("")📘 Rule violation ✓ Correctness
Description
The new tests assert citation keys via Optional.orElse(""), which converts absence into a sentinel
value and is discouraged by the Optional usage guideline. This can hide intent and makes assertions
less precise than asserting on the Optional directly.
Code

jablib/src/test/java/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest.java[60]

+        assertEquals("Har97", entries.getFirst().getCitationKey().orElse(""));
Evidence
PR Compliance ID 11 forbids using orElse("") as a sentinel default for Optional results; the added
assertions use getCitationKey().orElse("") to compare against expected strings.

AGENTS.md
jablib/src/test/java/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest.java[60-60]
jablib/src/test/java/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest.java[102-102]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new tests use `Optional.orElse(&amp;quot;&amp;quot;)` when asserting citation keys. This introduces a sentinel default and is discouraged by the project Optional guideline.
## Issue Context
`BibEntry.getCitationKey()` returns an `Optional`, so the tests can assert `Optional.of(&amp;quot;...&amp;quot;)` for present values and `Optional.empty()` for absent values.
## Fix Focus Areas
- jablib/src/test/java/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest.java[59-61]
- jablib/src/test/java/org/jabref/logic/importer/fileformat/CitaviXmlImporterTest.java[101-103]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Incomplete key sanitization🐞 Bug ✓ Correctness
Description
CitaviXmlImporter strips whitespace from <CitationKey> but leaves other BibTeX-disallowed characters
(e.g., comma, braces) intact. Since BibEntryWriter writes the citation key verbatim into the entry
header, such keys can produce malformed .bib output (e.g., "@article{Smith,2020,"), and will also be
flagged by JabRef’s citation-key validity checker.
Code

jablib/src/main/java/org/jabref/logic/importer/fileformat/CitaviXmlImporter.java[R525-528]

+        Optional.ofNullable(reference.citationKey())
+                .filter(key -> !key.isBlank())
+                .map(key -> key.replaceAll("\\s+", ""))
+                .ifPresent(entry::setCitationKey);
Evidence
The PR’s new logic only removes whitespace before calling setCitationKey. JabRef explicitly defines
a set of characters disallowed in BibTeX keys (including ',') and provides sanitizer utilities used
by other importers. The BibTeX writer does not escape/sanitize the key; it writes it directly, so a
disallowed character can break the serialized entry header. JabRef’s ValidCitationKeyChecker
determines validity by comparing against
CitationKeyGenerator.removeUnwantedCharactersWithKeepDiacritics, meaning keys with disallowed
characters are considered invalid.

jablib/src/main/java/org/jabref/logic/importer/fileformat/CitaviXmlImporter.java[522-528]
jablib/src/main/java/org/jabref/logic/citationkeypattern/CitationKeyGenerator.java[33-38]
jablib/src/main/java/org/jabref/logic/citationkeypattern/CitationKeyGenerator.java[94-114]
jablib/src/main/java/org/jabref/logic/bibtex/BibEntryWriter.java[151-158]
jablib/src/main/java/org/jabref/logic/integrity/ValidCitationKeyChecker.java[18-29]
jablib/src/main/java/org/jabref/logic/importer/fileformat/EndnoteImporter.java[238-240]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`CitaviXmlImporter` currently strips whitespace from `&amp;lt;CitationKey&amp;gt;` but does not remove BibTeX-disallowed characters (e.g., `,`, `{`, `}`), which can lead to malformed BibTeX output because the key is written verbatim in `@type{&amp;lt;key&amp;gt;,`.
### Issue Context
JabRef already centralizes citation key cleaning rules in `CitationKeyGenerator` and uses them elsewhere (e.g., `EndnoteImporter`). `BibEntryWriter` writes the citation key without escaping.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/importer/fileformat/CitaviXmlImporter.java[522-528]
- jablib/src/main/java/org/jabref/logic/citationkeypattern/CitationKeyGenerator.java[33-38]
- jablib/src/main/java/org/jabref/logic/citationkeypattern/CitationKeyGenerator.java[94-114]
- jablib/src/main/java/org/jabref/logic/importer/fileformat/EndnoteImporter.java[238-240]
### Suggested change
Replace the `replaceAll(&amp;quot;\\s+&amp;quot;, &amp;quot;&amp;quot;)` mapping with a call to `CitationKeyGenerator.removeUnwantedCharactersWithKeepDiacritics(...)` (and optionally `DEFAULT_UNWANTED_CHARACTERS`) so that whitespace *and* disallowed characters are removed. After cleaning, re-check blankness before setting the key.
### Tests
Add a unit test covering e.g. `&amp;lt;CitationKey&amp;gt;Smith, 2020&amp;lt;/CitationKey&amp;gt;` to ensure the imported key becomes `Smith2020` (or whatever policy you decide) and does not produce an invalid key per `ValidCitationKeyChecker`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Inline \s+ regex replaceAll📘 Rule violation ➹ Performance
Description
The importer strips whitespace using key.replaceAll("\\s+", ""), which recompiles the regex for
each processed entry. For repeated use during imports, the whitespace pattern should be precompiled
to a Pattern constant.
Code

jablib/src/main/java/org/jabref/logic/importer/fileformat/CitaviXmlImporter.java[R525-528]

+        Optional.ofNullable(reference.citationKey())
+                .filter(key -> !key.isBlank())
+                .map(key -> key.replaceAll("\\s+", ""))
+                .ifPresent(entry::setCitationKey);
Evidence
PR Compliance ID 9 requires using precompiled regex Patterns instead of inline regex usage for
repeated operations; the new code uses a regex-based replaceAll in the import path.

AGENTS.md
jablib/src/main/java/org/jabref/logic/importer/fileformat/CitaviXmlImporter.java[525-528]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Whitespace stripping uses `String.replaceAll(&amp;quot;\\s+&amp;quot;, &amp;quot;&amp;quot;)` in the import pipeline, which recompiles the regex per invocation.
## Issue Context
This code runs for each imported reference, so precompiling the pattern avoids repeated regex compilation and matches the project guideline.
## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/importer/fileformat/CitaviXmlImporter.java[525-528]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@github-actions github-actions Bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Mar 3, 2026
* Strip BibTeX-disallowed characters (comma, braces, etc.) from
  imported citation keys, not just whitespace
* Use Optional-based assertions instead of orElse("") sentinel
* Add test for disallowed character stripping
@testlens-app

This comment has been minimized.

@testlens-app

testlens-app Bot commented Mar 3, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: 1fc7f78
▶️ Tests: 10079 executed
🟡 Checks: 60/61 completed


Learn more about TestLens at testlens.app.

@Siedlerchr Siedlerchr enabled auto-merge March 3, 2026 19:10
@jabref-machine

Copy link
Copy Markdown
Collaborator

Your code currently does not meet JabRef's code guidelines. We use OpenRewrite to ensure "modern" Java coding practices. You can see which checks are failing by locating the box "Some checks were not successful" on the pull request page. To see the test output, locate "Source Code Tests / OpenRewrite (pull_request)" and click on it.

The issues found can be automatically fixed. Please execute the gradle task rewriteRun from the rewrite group of the Gradle Tool window in IntelliJ, then check the results, commit, and push.

@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: no-bot-comments labels Mar 3, 2026
@Siedlerchr Siedlerchr disabled auto-merge March 3, 2026 19:32
@Siedlerchr Siedlerchr merged commit 24a46d8 into JabRef:main Mar 3, 2026
61 of 71 checks passed
Siedlerchr added a commit that referenced this pull request Mar 5, 2026
…rg.openrewrite.recipe-rewrite-recipe-bom-3.25.0

* upstream/main: (35 commits)
  Chore: add dependency-management.md (#15278)
  Chore(deps): Bump dev.langchain4j:langchain4j-bom in /versions (#15277)
  New Crowdin updates (#15274)
  Chore(deps): Bump actions/upload-artifact from 6 to 7 (#15271)
  Chore(deps): Bump actions/download-artifact from 7 to 8 (#15270)
  Chore(deps): Bump docker/login-action from 3 to 4 (#15268)
  Fix threading issues in citations relations tab (#15233)
  Fix: Citavi XML importer now preserves citation keys (#14658) (#15257)
  Preserve no break spaces in Latex to Unicode conversion (#15174)
  Fix: open javafx.scene.control.skin to controlsfx (#15260)
  Reduce complexity in dependencies setup (restore) (#15194)
  New translations jabref_en.properties (French) (#15256)
  Fix: exception dialog shows up when moving sidepanel down/up (#15248)
  Implement reset for Name Display Preferences (#15136)
  Chore(deps): Bump net.bytebuddy:byte-buddy in /versions (#15252)
  Chore(deps): Bump io.zonky.test.postgres:embedded-postgres-binaries-bom (#15253)
  Chore(deps): Bump io.zonky.test:embedded-postgres in /versions (#15254)
  Chore(deps): Bump net.ltgt.errorprone from 5.0.0 to 5.1.0 in /jablib (#15251)
  New Crowdin updates (#15247)
  Refined the "Select files to import" page in "Search for unlinked local files" dialog (#15110)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: changes-required Pull requests that are not yet complete

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refine Citavi Importer

3 participants