Test seems to catch more than the template match should select
Here should go questions about transforming XML with XSLT and FOP.
-
- Posts: 24
- Joined: Thu Jan 07, 2021 10:44 am
Test seems to catch more than the template match should select
Post by DanOvergaard »
Hi,
I can't understand why the check below fails, as I think the template only "returns" the 2 "cbc:Description" nodes with the context (match) selected, but is seems that is also catch the node "cbc:Name".
The test should catch any nodes with the same name that has the same value in the "languageID" attribute
I hope someone can enlighten me
/Dan
Template
XML
I can't understand why the check below fails, as I think the template only "returns" the 2 "cbc:Description" nodes with the context (match) selected, but is seems that is also catch the node "cbc:Name".
The test should catch any nodes with the same name that has the same value in the "languageID" attribute
I hope someone can enlighten me

/Dan
Template
Code: Select all
<xsl:template match="doc:Invoice/cac:InvoiceLine/cac:Item/cbc:Description"/>
<xsl:if test="self::*[not(@languageID = following-sibling::*/@languageID)]">
<Error>
<Description>[W-LIB222] The attribute languageID should be used when more than one Description element is present</Description>
</Error>
</xsl:if>
</xsl:template>
Code: Select all
<cac;Invoice>
<cac:InvoiceLine>
<cac:Item>
<cbc:Description languageID="uk">Lorem ipsum dolor sit amet cons</cbc:Description>
<cbc:Description languageID="da">Lorem ipsum dolor sit amet cons</cbc:Description>
<cbc:Name languageID="da">Lorem ipsum dolo</cbc:Name>
<cac:SellersItemIdentification>
<cbc:ID>1</cbc:ID>
</cac:SellersItemIdentification>
</cac:Item>
</cac:InvoiceLine>
</cac;Invoice>
Last edited by DanOvergaard on Fri Dec 09, 2022 3:30 pm, edited 1 time in total.
-
- Posts: 9428
- Joined: Fri Jul 09, 2004 5:18 pm
Re: Test seems to catch more than the template match should select
Hi,
An xpath like this "following-sibling::*" matches all following siblings, not just the next sibling.
So in the context of "<cbc:Description languageID="uk">" the "following-sibling::*" xpath returns a sequence of "<cbc:Description languageID="da">", "<cbc:Name languageID="da">", "<cac:SellersItemIdentification>".
Probably your xpath expression should look like this:
to look only at the first following sibling element.
In such cases you can use <xsl:message> expressions to debug the returned values, for example add an xsl:message before the xsl:if:
Regards,
Radu
An xpath like this "following-sibling::*" matches all following siblings, not just the next sibling.
So in the context of "<cbc:Description languageID="uk">" the "following-sibling::*" xpath returns a sequence of "<cbc:Description languageID="da">", "<cbc:Name languageID="da">", "<cac:SellersItemIdentification>".
Probably your xpath expression should look like this:
Code: Select all
<xsl:if test="self::*[not(@languageID = following-sibling::*[1]/@languageID)]">
In such cases you can use <xsl:message> expressions to debug the returned values, for example add an xsl:message before the xsl:if:
Code: Select all
<xsl:message><xsl:copy-of select="following-sibling::*/@languageID"/></xsl:message>
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
<oXygen/> XML Editor
http://www.oxygenxml.com
-
- Posts: 24
- Joined: Thu Jan 07, 2021 10:44 am
Re: Test seems to catch more than the template match should select
Post by DanOvergaard »
Hi Radu,
Thanks for your feedback - your explanation makes sense.
Unfortunate, your suggestion didn't solve my problem. What I want is to check if any of the "cac:Description" have the same "languageID". Do you have any suggestions ?
This should not fail
This should fail
Note
I have added a zip-file with the full xml-file and Schematron
Thanks for your feedback - your explanation makes sense.
Unfortunate, your suggestion didn't solve my problem. What I want is to check if any of the "cac:Description" have the same "languageID". Do you have any suggestions ?
This should not fail
Code: Select all
<cbc:Description languageID="uk">Lorem ipsum dolor sit amet cons</cbc:Description>
<cbc:Description languageID="da">Lorem ipsum dolor sit amet cons</cbc:Description>
<cbc:Name languageID="da">Lorem ipsum dolo</cbc:Name>
Code: Select all
<cbc:Description languageID="da">Lorem ipsum dolor sit amet cons</cbc:Description>
<cbc:Description languageID="uk">Lorem ipsum dolor sit amet cons</cbc:Description>
<cbc:Description languageID="da">Lorem ipsum dolor sit amet cons</cbc:Description>
<cbc:Name languageID="da">Lorem ipsum dolo</cbc:Name>
I have added a zip-file with the full xml-file and Schematron
Xml_and_XLS.zip
- The error occurs in line 32892You do not have the required permissions to view the files attached to this post.
-
- Posts: 102
- Joined: Tue Aug 19, 2014 12:04 pm
Re: Test seems to catch more than the template match should select
Post by Martin Honnen »
If you use a context of e.g. `cac:Item[cbc:Description[2]]` you can then check e.g. `count(distinct-values(cbc:Description/@languageID)) lt count(cbc:Description/@languageID)`.
Or perhaps in terms of Schematron
Or perhaps in terms of Schematron
Code: Select all
<pattern>
<rule context="cac:Item[cbc:Description[2]]">
<assert test="count(distinct-values(cbc:Description/@languageID)) eq count(cbc:Description/@languageID)">languageID needs to be unique</assert>
</rule>
</pattern>
-
- Posts: 24
- Joined: Thu Jan 07, 2021 10:44 am
Re: Test seems to catch more than the template match should select
Post by DanOvergaard »
Hi,
Appreciate your help but unfortunately, your suggestion didn't work (or I implemented it wrong) as it still failed if there was a "languageID" matching outside the "Description" context.
I found the solution listed below, but is there a way to translate this to "Schematron schema" (sch:)
Regs,
Dan
Appreciate your help but unfortunately, your suggestion didn't work (or I implemented it wrong) as it still failed if there was a "languageID" matching outside the "Description" context.
I found the solution listed below, but is there a way to translate this to "Schematron schema" (sch:)
Code: Select all
<xsl:for-each-group select="cac:Item/cbc:Description" group-by="@languageID">
<xsl:if test="count(current-group()) > 1">
<Error>
<Description>[W-LIB223] Multilanguage error. </Description>
</Error>
</xsl:if>
</xsl:for-each-group>
Dan
-
- Posts: 102
- Joined: Tue Aug 19, 2014 12:04 pm
Re: Test seems to catch more than the template match should select
Post by Martin Honnen »
Schematron, if implemented in XSLT, usually allows you to make use of xsl:function or xsl:key so if you want to use that grouping construct you could try to put it into a function you call then from your Schematron rule or, as grouping/keying is basically the same approach, use e.g.
and then in Schematron
Code: Select all
<xsl:key name="language-group" match="cac:Item/cbc:Description" use="@languageID"/>
Code: Select all
<rule context="cac:Item/cbc:Description">
<assert test="not(key('language-group',
@languageID)[2])">languageID should be unique</assert>
</rule>
-
- Posts: 24
- Joined: Thu Jan 07, 2021 10:44 am
Re: Test seems to catch more than the template match should select
Post by DanOvergaard »
Hi Martin,
I will put your suggestion to test during the week – Thanks
My “for-each-group” solution has run into a problem which I hope you can help with. The solution I found is not working in the production environment, as the more than 100 different calls are done with a “too” specific “Context” for the “for-each-group” to work.
The rule was original created as stated below and then called with a context ending on “cbc:Description” (eg.: doc:Invoice/cac:InvoiceLine/cac:Item/cbc:Description"), but it’s not working as it catch more then just the “cbc:Description” elements.
What I need is a rule that catch if there are multiple "languageID’s" with the same value on multiple “cbc:Description” elements in the same segment (See the "Xml example" below), but as the rule already is called from countless places with different context I can’t change the context.
Can you see any solution where a test can work in the context described?
Original rule
Example of two different calls from the production
Xml example
I will put your suggestion to test during the week – Thanks
My “for-each-group” solution has run into a problem which I hope you can help with. The solution I found is not working in the production environment, as the more than 100 different calls are done with a “too” specific “Context” for the “for-each-group” to work.
The rule was original created as stated below and then called with a context ending on “cbc:Description” (eg.: doc:Invoice/cac:InvoiceLine/cac:Item/cbc:Description"), but it’s not working as it catch more then just the “cbc:Description” elements.
What I need is a rule that catch if there are multiple "languageID’s" with the same value on multiple “cbc:Description” elements in the same segment (See the "Xml example" below), but as the rule already is called from countless places with different context I can’t change the context.
Can you see any solution where a test can work in the context described?
Original rule
Code: Select all
<sch:rule abstract="true" id="DescriptionLanguageCheck">
<sch:report test="following-sibling::*/@languageID = self::*/@languageID">[W-LIB223] Multilanguage error. Replicated Description elements with same languageID attribute value</sch:report>
</sch:rule>
Example of two different calls from the production
Code: Select all
<sch:rule context="doc:Invoice/cac:InvoiceLine/cac:Item">
<sch:extends rule="DescriptionLanguageCheck"/>
</sch:rule>
Code: Select all
<sch:rule context="doc:Invoice/cac:InvoiceLine/cac:Item/cac:TransactionConditions/cbc:Description">
<sch:extends rule="DescriptionLanguageCheck"/>
</sch:rule>
Xml example
Code: Select all
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cac:InvoiceLine>
<cac:Item>
<cbc:Description languageID="uk">Lorem ipsum dolor sit amet cons</cbc:Description>
<cbc:Description languageID="da">Lorem ipsum dolor sit amet cons</cbc:Description>
<cbc:Description languageID="da">Lorem ipsum dolor sit amet cons1</cbc:Description>
<cbc:Name languageID="da">Lorem ipsum dolo</cbc:Name>
<cac:SellersItemIdentification>
<cbc:ID>1</cbc:ID>
</cac:SellersItemIdentification>
<cac:TransactionConditions>
<cbc:Description languageID="da">Lorem ipsum dolor sit amet cons</cbc:Description>
</cac:TransactionConditions>
</cac:Item>
</cac:InvoiceLine>
</Invoice>
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