using XSL to count elements
Here should go questions about transforming XML with XSLT and FOP.
-
- Posts: 3
- Joined: Fri Oct 15, 2021 7:08 am
using XSL to count elements
Post by T_BugReporter »
Hello! I've been trying for several weeks to learn XSL and use it to manipulate some data we receive in XML format, but I'm not finding a whole lot of resources for this language on the Internet (so if you've seen this same question posted somewhere else, I apologize for the duplication). Here's an example of the data files we receive (scrubbed of confidential information), the XSL code I came up with to manipulate it, and the resulting output:
Sample-Input.xml
Sample-Code.xsl
Sample-Output.html
(I know I have more problems with this code than just the one I asked about here, but I have a feeling that once I understand what I'm doing wrong with this problem, the other pieces will fall into place.)
The answers I'm expecting to get in the count column should be 3, 1, 0, and 3; but it seems to be counting not just descendants, but all the matching data points from the current position to the end - and recounting them every time the position changes.
My question is: Why is it that the "following-sibling" key word that I'm using is finding not only siblings (nodes having the same parent node), but also "cousins" (nodes at the same level, regardless of which node is the parent)? And, of course, how do I fix it?
Sample-Input.xml
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Entry1</key>
<dict>
<key>EntryCollectionA</key>
<dict>
<key>ECA Identifier</key>
<dict>
<key>ECADetail1</key>
<string>The quick brown fox</string>
<key>ECADetail2</key>
<integer>1112</integer>
</dict>
</dict>
<key>EntryCollectionB</key>
<dict>
<key>Identifier for the first ECB</key>
<dict>
<key>ECBMinorDetail1</key>
<false/>
<key>ECBMinorDetail2</key>
<dict>
<key>EBC2's name</key>
<string>jumps over the lazy dog.</string>
</dict>
<key>ECBImportantDetail3</key>
<string>three</string>
<key>ECBImportantDetail4</key>
<string>four</string>
<key>ECBImportantDetail5</key>
<string>five</string>
<key>ECBIrrelevantToMe</key>
<data>
yadda+yadda+yadda/yadda+yaddayaddayaddayadda
</data>
<key>ECBIrrelevantToo</key>
<integer>987654321</integer>
</dict>
<key>second ECB for Entry1 has a different title</key>
<dict>
<key>ECBMinorDetail1</key>
<false/>
<key>ECBMinorDetail2</key>
<dict>
<key>a name for Ecb2 goes here</key>
<string>vaults above the recalcitrant canine.</string>
</dict>
<key>ECBImportantDetail3</key>
<string>is the number of the count,</string>
<key>ECBImportantDetail4</key>
<string>and what the number of the count shall be</string>
<key>ECBImportantDetail5</key>
<string>is right out.</string>
<key>ECBIrrelevantToMe</key>
<data>
MORE/inde+cipher+able/and+IRReleVaNTinbase64
</data>
<key>ECBIrrelevantToo</key>
<integer>19283746</integer>
</dict>
<key>Entry1 third ECB</key>
<dict>
<key>ECBMinorDetail1</key>
<true/>
<key>ECBMinorDetail2</key>
<dict>
<key>Ecb3 has a name</key>
<string>is intimidated by the sleeping dragon.</string>
</dict>
<key>ECBImportantDetail3</key>
<string>is a magic number</string>
<key>ECBImportantDetail4</key>
<string>is the legs in a zoo</string>
<key>ECBImportantDetail5</key>
<string>ready or not, here I come!</string>
<key>ECBIrrelevantToMe</key>
<data>
WiLlY0USt1lLFe3dMe/WhEnImSiXtYfOuR/60plUsF0R
</data>
<key>ECBIrrelevantToo</key>
<integer>6406406566</integer>
</dict>
</dict>
<key>ImportantDatum6</key>
<string>what this data pertains to</string>
<key>ImportantDatum7</key>
<string>reference code</string>
<key>ImportantDatum8</key>
<string>one,two</string>
<key>whoCares</key>
<integer>1</integer>
<key>iDo-aboutThisOne</key>
<string>999</string>
<key>ANDagain</key>
<string>eeny</string>
<key>moreSillyData</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
<key>bucketObits</key>
<string>more characters</string>
<key>bitObuckets</key>
<string>textity textext</string>
<key>amount</key>
<integer>66645714</integer>
<key>code</key>
<integer>765432109</integer>
<key>subcode</key>
<integer>828474104</integer>
</dict>
<key>second entry</key>
<dict>
<key>EntryCollectionA</key>
<dict>
<key>5564738291</key>
<dict>
<key>wardrobe</key>
<string>lionWitch</string>
<key>buuleeun</key>
<false/>
</dict>
</dict>
<key>EntryCollectionB</key>
<dict>
<key>2's ECB name</key>
<dict>
<key>tuuleeun</key>
<false/>
<key>batchCodes</key>
<dict>
<key>5564738291</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
</dict>
<key>ImportantDatum7</key>
<string>sequence identifier</string>
<key>ImportantDatum8</key>
<string>three,four</string>
<key>iDo-aboutThisOne</key>
<string>thuh-ree</string>
<key>moreSillyData</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
<key>subcode</key>
<integer>841391812</integer>
</dict>
</dict>
<key>ImportantDatum6</key>
<string>another collection of data</string>
<key>ImportantDatum7</key>
<string>identifier string</string>
<key>ImportantDatum8</key>
<string>buckle my shoe</string>
<key>whoCares</key>
<integer>1</integer>
<key>iDo-aboutThisOne</key>
<string>again</string>
<key>ANDagain</key>
<string>meeny</string>
<key>moreSillyData</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
<key>bucketObits</key>
<string>say what you want</string>
<key>amount</key>
<integer>51736576</integer>
<key>code</key>
<integer>456789012</integer>
<key>subcode</key>
<integer>841391812</integer>
</dict>
<key>another main entry</key>
<dict>
<key>EntryCollectionA</key>
<dict>
<key>5564738291</key>
<dict>
<key>wardrobe</key>
<string>lionWitch</string>
<key>buuleeun</key>
<false/>
</dict>
</dict>
<key>ImportantDatum6</key>
<string>my third data set</string>
<key>ImportantDatum7</key>
<string>ID code</string>
<key>ImportantDatum8</key>
<string>five,six</string>
<key>whoCares</key>
<integer>1</integer>
<key>iDo-aboutThisOne</key>
<string>tenAgain</string>
<key>ANDagain</key>
<string>miney</string>
<key>moreSillyData</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
<key>bucketObits</key>
<string>more to say</string>
<key>amount</key>
<integer>1576960</integer>
<key>code</key>
<integer>1248163264</integer>
<key>subcode</key>
<integer>842184218</integer>
</dict>
<key>final sample</key>
<dict>
<key>EntryCollectionA</key>
<dict>
<key>5564738291</key>
<dict>
<key>wardrobe</key>
<string>lionWitch</string>
<key>buuleeun</key>
<false/>
</dict>
</dict>
<key>EntryCollectionB</key>
<dict>
<key>ECB (but for #4?)</key>
<dict>
<key>tuuleeun</key>
<false/>
<key>batchCodes</key>
<dict>
<key>5564738291</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
</dict>
<key>ImportantDatum7</key>
<string>name, of sorts</string>
<key>ImportantDatum8</key>
<string>nine,ten</string>
<key>iDo-aboutThisOne</key>
<string>tenAgain</string>
<key>moreSillyData</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
<key>subcode</key>
<integer>84218421</integer>
</dict>
<key>four's second ECB</key>
<dict>
<key>tuuleeun</key>
<false/>
<key>batchCodes</key>
<dict>
<key>5564738291</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
</dict>
<key>ImportantDatum7</key>
<string>three is also 7?</string>
<key>ImportantDatum8</key>
<string>eight is also four</string>
<key>iDo-aboutThisOne</key>
<string>cra-zee</string>
<key>moreSillyData</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
<key>subcode</key>
<integer>474828131</integer>
</dict>
<key>369,121518</key>
<dict>
<key>tuuleeun</key>
<false/>
<key>batchCodes</key>
<dict>
<key>5564738291</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
</dict>
<key>ImportantDatum7</key>
<string>code name for this item</string>
<key>ImportantDatum8</key>
<string>close the door</string>
<key>iDo-aboutThisOne</key>
<string>heaven</string>
<key>moreSillyData</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
<key>subcode</key>
<integer>963852741</integer>
</dict>
</dict>
<key>ImportantDatum6</key>
<string>and here's another group of data</string>
<key>ImportantDatum7</key>
<string>code name for this item</string>
<key>ImportantDatum8</key>
<string>do it again</string>
<key>whoCares</key>
<integer>1</integer>
<key>iDo-aboutThisOne</key>
<string>heaven</string>
<key>ANDagain</key>
<string>moe</string>
<key>moreSillyData</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</data>
<key>bucketObits</key>
<string>piece of text</string>
<key>amount</key>
<integer>19189760</integer>
<key>code</key>
<integer>567890123</integer>
<key>supportedDeviceTypes</key>
<integer>7</integer>
<key>subcode</key>
<integer>303030303</integer>
</dict>
</dict>
</plist>
Code: Select all
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Heading and preliminary stuff</h2>
<table>
<tr>
<th bgcolor="#336699">Main</th>
<th>count</th>
<th bgcolor="#3366cc">EntryCollectionB</th>
<th bgcolor="#339966">EntryCollectionB/<br/>
ECBImportantDetail3</th>
<th bgcolor="#3399cc">EntryCollectionB/<br/>
ECBImportantDetail4</th>
<th bgcolor="#33cc66">EntryCollectionB/<br/>
ECBImportantDetail5</th>
<th bgcolor="#33cc99">ImportantDatum6</th>
<th bgcolor="#663399">ImportantDatum7</th>
<th bgcolor="#6633cc">ImportantDatum8</th>
<th bgcolor="#669933">iDo-aboutThisOne</th>
<th bgcolor="#6699cc">ANDagain</th>
<th bgcolor="#66cc33">amount</th>
</tr>
<xsl:for-each select="plist/dict/key">
<tr>
<td bgcolor="#66cc99"><xsl:value-of select="." /></td>
<td><xsl:value-of select="count(following-sibling::dict/key[text()='EntryCollectionB']/
following-sibling::dict/key)" /></td>
<td bgcolor="#993366"><xsl:value-of select="following-sibling::dict/key[text()='EntryCollectionB']/
following-sibling::dict/key" /></td>
<td bgcolor="#9933cc"><xsl:value-of select="following-sibling::dict/key[text()='EntryCollectionB']/
following-sibling::dict/key/
following-sibling::dict/key[text()='ECBImportantDetail3']/
following-sibling::string" /></td>
<td bgcolor="#996633"><xsl:value-of select="following-sibling::dict/key[text()='EntryCollectionB']/
following-sibling::dict/key/
following-sibling::dict/key[text()='ECBImportantDetail4']/
following-sibling::string" /></td>
<td bgcolor="#9966cc"><xsl:value-of select="following-sibling::dict/key[text()='EntryCollectionB']/
following-sibling::dict/key/
following-sibling::dict/key[text()='ECBImportantDetail5']/
following-sibling::string" /></td>
<td bgcolor="#99cc33"><xsl:value-of select="following-sibling::dict/key[text()='ImportantDatum6']/
following-sibling::string" /></td>
<td bgcolor="#99cc66"><xsl:value-of select="following-sibling::dict/key[text()='ImportantDatum7']/
following-sibling::string" /></td>
<td bgcolor="#cc3366"><xsl:value-of select="following-sibling::dict/key[text()='ImportantDatum8']/
following-sibling::string" /></td>
<td bgcolor="#cc3399"><xsl:value-of select="following-sibling::dict/key[text()='iDo-aboutThisOne']/
following-sibling::string" /></td>
<td bgcolor="#cc6633"><xsl:value-of select="following-sibling::dict/key[text()='ANDagain']/
following-sibling::string" /></td>
<td bgcolor="#cc6699"><xsl:value-of select="following-sibling::dict/key[text()='amount']/
following-sibling::integer" /></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Code: Select all
<!DOCTYPE HTML><html>
<body>
<h2>Heading and preliminary stuff</h2>
<table>
<tr>
<th bgcolor="#336699">Main</th>
<th>count</th>
<th bgcolor="#3366cc">EntryCollectionB</th>
<th bgcolor="#339966">EntryCollectionB/<br>
ECBImportantDetail3</th>
<th bgcolor="#3399cc">EntryCollectionB/<br>
ECBImportantDetail4</th>
<th bgcolor="#33cc66">EntryCollectionB/<br>
ECBImportantDetail5</th>
<th bgcolor="#33cc99">ImportantDatum6</th>
<th bgcolor="#663399">ImportantDatum7</th>
<th bgcolor="#6633cc">ImportantDatum8</th>
<th bgcolor="#669933">iDo-aboutThisOne</th>
<th bgcolor="#6699cc">ANDagain</th>
<th bgcolor="#66cc33">amount</th>
</tr>
<tr>
<td bgcolor="#66cc99">Entry1</td>
<td>7</td>
<td bgcolor="#993366">Identifier for the first ECB</td>
<td bgcolor="#9933cc">three</td>
<td bgcolor="#996633">four</td>
<td bgcolor="#9966cc">five</td>
<td bgcolor="#99cc33">what this data pertains to</td>
<td bgcolor="#99cc66">reference code</td>
<td bgcolor="#cc3366">one,two</td>
<td bgcolor="#cc3399">999</td>
<td bgcolor="#cc6633">eeny</td>
<td bgcolor="#cc6699">66645714</td>
</tr>
<tr>
<td bgcolor="#66cc99">second entry</td>
<td>4</td>
<td bgcolor="#993366">2's ECB name</td>
<td bgcolor="#9933cc"></td>
<td bgcolor="#996633"></td>
<td bgcolor="#9966cc"></td>
<td bgcolor="#99cc33">another collection of data</td>
<td bgcolor="#99cc66">identifier string</td>
<td bgcolor="#cc3366">buckle my shoe</td>
<td bgcolor="#cc3399">again</td>
<td bgcolor="#cc6633">meeny</td>
<td bgcolor="#cc6699">51736576</td>
</tr>
<tr>
<td bgcolor="#66cc99">another main entry</td>
<td>3</td>
<td bgcolor="#993366">ECB (but for #4?)</td>
<td bgcolor="#9933cc"></td>
<td bgcolor="#996633"></td>
<td bgcolor="#9966cc"></td>
<td bgcolor="#99cc33">my third data set</td>
<td bgcolor="#99cc66">ID code</td>
<td bgcolor="#cc3366">five,six</td>
<td bgcolor="#cc3399">tenAgain</td>
<td bgcolor="#cc6633">miney</td>
<td bgcolor="#cc6699">1576960</td>
</tr>
<tr>
<td bgcolor="#66cc99">final sample</td>
<td>3</td>
<td bgcolor="#993366">ECB (but for #4?)</td>
<td bgcolor="#9933cc"></td>
<td bgcolor="#996633"></td>
<td bgcolor="#9966cc"></td>
<td bgcolor="#99cc33">and here's another group of data</td>
<td bgcolor="#99cc66">code name for this item</td>
<td bgcolor="#cc3366">do it again</td>
<td bgcolor="#cc3399">heaven</td>
<td bgcolor="#cc6633">moe</td>
<td bgcolor="#cc6699">19189760</td>
</tr>
</table>
</body>
</html>
The answers I'm expecting to get in the count column should be 3, 1, 0, and 3; but it seems to be counting not just descendants, but all the matching data points from the current position to the end - and recounting them every time the position changes.
My question is: Why is it that the "following-sibling" key word that I'm using is finding not only siblings (nodes having the same parent node), but also "cousins" (nodes at the same level, regardless of which node is the parent)? And, of course, how do I fix it?
-
- Posts: 9420
- Joined: Fri Jul 09, 2004 5:18 pm
Re: using XSL to count elements
Hi,
So inside the for-each:
you are in the context of a "key" element, for example let's say we are in the context of <key>Entry1</key>.
Then you evaluate this Xpath:
"following-sibling::dict/key[text()='EntryCollectionB']" will match three "key" nodes because there are 3 keys "<key>EntryCollectionB</key>" in the same file. And for each of these 3 nodes will return all key elements from the following-sibling "dict" elements "following-sibling::dict/key)".
To test XPath expressions in a certain context in Oxygen you can place for example the caret inside the " <key>Entry1</key>" element and then run the XPath using the XPath toolbar.
Regards,
Radu
So inside the for-each:
Code: Select all
<xsl:for-each select="plist/dict/key">
Then you evaluate this Xpath:
Code: Select all
<xsl:value-of select="count(following-sibling::dict/key[text()='EntryCollectionB']/
following-sibling::dict/key)" />
To test XPath expressions in a certain context in Oxygen you can place for example the caret inside the " <key>Entry1</key>" element and then run the XPath using the XPath toolbar.
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
<oXygen/> XML Editor
http://www.oxygenxml.com
-
- Posts: 3
- Joined: Fri Oct 15, 2021 7:08 am
Re: using XSL to count elements
Post by T_BugReporter »
After spending too much spare time reading everything I could find on the Internet that seems relevant, plus downloading and playing with several XML tools, I'm still confused - mainly because the XQuery expression that's giving me these bizarre answers is not much different from the other ones that are giving me the results I expect.
I'm going to try to explain my logic in constructing the "count()" expression in my Sample-Code.xsl file; I would appreciate having the flaws in this logic pointed out to me. (Apologies for the long lines below; it was the easiest way I could think of to illustrate my thought process.)
First off, I'm iterating over "plist/dict/key", which should (and, apparently, does) trigger four times for the Sample-Input.xml: on encountering "<key>Entry1</key>", "<key>second entry</key>", "<key>another main entry</key>", and "<key>final sample</key>". Now, for the moment, concentrating on "Entry1" and ignoring what it'll find on subsequent passes*, I output "value-of select='.'" ("Entry1") to the first column of the HTML table, and then ...
* Or maybe I shouldn't be ignoring that? Or I should write something else into the expression to insure that it does ignore that?
Where else am I going wrong?
I'm going to try to explain my logic in constructing the "count()" expression in my Sample-Code.xsl file; I would appreciate having the flaws in this logic pointed out to me. (Apologies for the long lines below; it was the easiest way I could think of to illustrate my thought process.)
First off, I'm iterating over "plist/dict/key", which should (and, apparently, does) trigger four times for the Sample-Input.xml: on encountering "<key>Entry1</key>", "<key>second entry</key>", "<key>another main entry</key>", and "<key>final sample</key>". Now, for the moment, concentrating on "Entry1" and ignoring what it'll find on subsequent passes*, I output "value-of select='.'" ("Entry1") to the first column of the HTML table, and then ...
Code: Select all
<!-- attempt to calculate a count, ... -->
<xsl:value-of select="count( )" />
<!-- (working backwards thru the expression), specifically of "key"s ... -->
<xsl:value-of select="count( key)" />
<!-- that are children of "dict"s, ... -->
<xsl:value-of select="count( dict/key)" />
<!-- that have a "following-sibling" relationship ... -->
<xsl:value-of select="count( following-sibling::dict/key)" />
<!-- to some (parent level) "key" ... -->
<xsl:value-of select="count( key/following-sibling::dict/key)" />
<!-- having "EntryCollectionB" as its "text()" ... -->
<xsl:value-of select="count( key[text()='EntryCollectionB']/following-sibling::dict/key)" />
<!-- that is a child of a "dict" ... -->
<xsl:value-of select="count( dict/key[text()='EntryCollectionB']/following-sibling::dict/key)" />
<!-- that is a "following-sibling" ... -->
<xsl:value-of select="count(following-sibling::dict/key[text()='EntryCollectionB']/following-sibling::dict/key)" />
<!-- of the "plist/dict/key" that's currently being worked on - "Entry1". -->
Where else am I going wrong?
-
- Posts: 9420
- Joined: Fri Jul 09, 2004 5:18 pm
Re: using XSL to count elements
Hi,
I'm afraid I do not have much time to look into this, maybe you can use our Oxygen XSLT Debugger perspective to step through the XML and maybe evaluate certain XPath expressions in a certain context.
Regards,
Radu
I'm afraid I do not have much time to look into this, maybe you can use our Oxygen XSLT Debugger perspective to step through the XML and maybe evaluate certain XPath expressions in a certain context.
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
<oXygen/> XML Editor
http://www.oxygenxml.com
-
- Posts: 3
- Joined: Fri Oct 15, 2021 7:08 am
Re: using XSL to count elements
Post by T_BugReporter »
OMG - it took me two months, including countless hours reading, experimenting, and testing - but I've finally constructed a query that gets the results I was looking for:
My newly working modification:
I still don't understand why this three character addition is necessary, so my second question still stands:
Excerpt from my original XSL:The answers I'm expecting to get in the count column should be 3, 1, 0, and 3
Code: Select all
<td><xsl:value-of select="count(following-sibling::dict/
key[text()='EntryCollectionB']/
following-sibling::dict/key)" /></td>
Code: Select all
<td><xsl:value-of select="count(following-sibling::dict[1]/
key[text()='EntryCollectionB']/
following-sibling::dict/key)" /></td>
However, given how much time and effort I've wasted in trying to understand this, I'm at the point of no longer caring why the code works, as long as it works. You can consider this question closed.Why is it that the "following-sibling" key word that I'm using is finding not only siblings (nodes having the same parent node), but also "cousins" (nodes at the same level, regardless of which node is the parent)?
-
- Posts: 1016
- Joined: Wed Nov 16, 2005 11:11 am
Re: using XSL to count elements
Post by alex_jitianu »
Hello,
The following-sibling:* axis only matches on the brothers of the current node as opposed to following:* axis. Perhaps your behavior is related with the fact that you have a template that fires multiple times so the following-sibling:* expression is executed multiple times. Oxygen's XSLT Debugger should help if you execute the XSLT step by step.
Best regards,
Alex
The following-sibling:* axis only matches on the brothers of the current node as opposed to following:* axis. Perhaps your behavior is related with the fact that you have a template that fires multiple times so the following-sibling:* expression is executed multiple times. Oxygen's XSLT Debugger should help if you execute the XSLT step by step.
Best regards,
Alex
Jump to
- Oxygen XML Editor/Author/Developer
- ↳ Feature Request
- ↳ Common Problems
- ↳ DITA (Editing and Publishing DITA Content)
- ↳ SDK-API, Frameworks - Document Types
- ↳ DocBook
- ↳ TEI
- ↳ XHTML
- ↳ Other Issues
- Oxygen XML Web Author
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Content Fusion
- ↳ Feature Request
- ↳ Common Problems
- Oxygen JSON Editor
- ↳ Feature Request
- ↳ Common Problems
- Oxygen PDF Chemistry
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Feedback
- ↳ Feature Request
- ↳ Common Problems
- Oxygen XML WebHelp
- ↳ Feature Request
- ↳ Common Problems
- XML
- ↳ General XML Questions
- ↳ XSLT and FOP
- ↳ XML Schemas
- ↳ XQuery
- NVDL
- ↳ General NVDL Issues
- ↳ oNVDL Related Issues
- XML Services Market
- ↳ Offer a Service