Project

Profile

Help

Removal of optional elements

Added by Anonymous about 12 years ago

Legacy ID: #7093281 Legacy Poster: Alexander Keim (alex116)

Hello, I'd like to run an XSLT that removes all elements from the input XML document which are optional according to the related schema. Is that possible? Is there a way to determine if an element ist mandatory or optional??? Regards - Alex


Replies (4)

Please register to reply

RE: Removal of optional elements - Added by Anonymous about 12 years ago

Legacy ID: #7093577 Legacy Poster: Michael Kay (mhkay)

Assuming a schema-aware transformation, you could try something like this: <xsl:template match="*[my:isOptional(.., node-name())]"/> where my:isOptional maps to a Java extension function whose logic is a method such as public static boolean isOptional(NodeInfo parent, QNameValue childName) { Configuration config = parent.getConfiguration(); SchemaType parentType = config.getSchemaType(parent.getTypeAnnotation()); int fp = config.getNamePool().allocate("", childName.getComponent(Component.NAMESPACE), childName.getComponent(Component.LOCALNAME)); int cardinality = ((ComplexType)parentType).getElementParticleCardinality(fp); return Cardinality.allowsZero(cardinality); } Not tested, and there's probably some detail missing, but hopefully this is an avenue you could explore.

RE: Removal of optional elements - Added by Anonymous about 12 years ago

Legacy ID: #7093660 Legacy Poster: Alexander Keim (alex116)

Thanks for the fast response. I'll give your suggestion a try and report on the outcome. Best regards - Alex

RE: Removal of optional elements - Added by Anonymous about 12 years ago

Legacy ID: #7100546 Legacy Poster: Alexander Keim (alex116)

Got your code running. Just had to modify one line to get it compiled: int fp = config.getNamePool().allocate("", childName.getComponent(Component.NAMESPACE).toString(), childName.getComponent(Component.LOCALNAME).toString()); Nevertheless the extension function always returns true and I'm not so skilled in the saxon libs to see the actual problem. If you could spare some of your valuable time and have a second look at code - that would really be great!!!

RE: Removal of optional elements - Added by Anonymous about 12 years ago

Legacy ID: #7100756 Legacy Poster: Michael Kay (mhkay)

Are you sure you validated the input document? It works for me: working test case below. I had to use the match pattern //[...] to avoid deleting top-level elements. I think that when you match the outermost element, .. will be a document node, and the extension function doesn't handle this case. At the next level down you typically find an element with minOccurs=0, maxOccurs=unbounded which counts as optional under this rule. So you may need to refine the rules. public void testExtensionWithSchemaAccecss() { // Create a Processor instance. try { Processor proc = new Processor(true); proc.setConfigurationProperty("http://saxon.sf.net/feature/timing", "true"); XsltCompiler comp = proc.newXsltCompiler(); comp.setSchemaAware(true); StringReader sr = new StringReader("<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:my='java:s9apitest.TestXsltTransformer' exclude-result-prefixes='my'>" + "<xsl:template match=''><xsl:copy><xsl:copy-of select='@'/><xsl:apply-templates/></xsl:copy></xsl:template>\n" + "<xsl:template match='///*[my:isOptional(.., node-name(.))]'/> \n" + "</xsl:stylesheet>"); XsltExecutable exec = comp.compile(new StreamSource(sr)); XsltTransformer transformer = exec.load(); SchemaManager sm = proc.getSchemaManager(); sm.load(new StreamSource(new File("c:/MyJava/testdata/books.xsd"))); DocumentBuilder builder = proc.newDocumentBuilder(); builder.setSchemaValidator(sm.newSchemaValidator()); XdmNode books = builder.build(new File("c:/MyJava/testdata/books.xml")); transformer.setInitialContextNode(books); // Create a serializer //String outfile = @"C:/MyJava/users/caffo/Output.xml"; StringWriter sw = new StringWriter(); Serializer serializer = new Serializer(); serializer.setOutputProperty(Serializer.Property.INDENT, "yes"); serializer.setOutputWriter(sw); transformer.setDestination(serializer); transformer.transform(); assertTrue(sw.toString().contains("TITLE")); assertFalse(sw.toString().contains("AUTHOR")); } catch (SaxonApiException e) { e.printStackTrace(); fail(e.getMessage()); } } /** * Sample extension function - explores schema information */ public static boolean isOptional(NodeInfo parent, QNameValue childName) throws Exception { Configuration config = parent.getConfiguration(); SchemaType parentType = config.getSchemaType(parent.getTypeAnnotation()); int fp = config.getNamePool().allocate("", childName.getComponent(Component.NAMESPACE).getStringValue(), childName.getComponent(Component.LOCALNAME).getStringValue()); int cardinality = ((ComplexType)parentType).getElementParticleCardinality(fp); return Cardinality.allowsZero(cardinality); }

    (1-4/4)

    Please register to reply