Help with identifying unique text elements

Discussion in 'XML' started by daldridge@gmail.com, Oct 9, 2006.

  1. Guest

    I have a unique-elements/sorting question (who doesn't?), but haven't
    yet been able to get appropriate template/select/for-each processing
    working. I don't fully grok the Muenchian technique yet (still an XSLT
    n00b), but I'm not sure that's the way to go anyway...

    What I'm trying to accomplish is generation of XML Schema output from a
    given XML input, with "xs:import" elements in the output with the
    "namespace" and "schemaLocation" attributes corresponding to a unique
    set of text values found in the input file. (I don't need assistance
    with the required <xsl:element> output, as I have a solution for that
    figured out. Just the appropriate select/group/for-each processing, as
    the xs:import's must be unique...)

    If I were to put the select statement in words, I think this is what I
    want to accomplish:
    "determine the set of unique text values of all elements named
    'PropertyClassName', which have a parent of
    'PropertyClassSpec/PropertyClassVec/PropertyClassNames' or
    'PropertyClassSpec/PropertyClass'".

    Here is a sample input .XML file:

    <?xml version="1.0" encoding="UTF-8"?>
    <PropertyClassSpec xmlns="http://someDomain/PropertyClassSpec"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://someDomain/PropertyClassSpec
    PropertyClassSpec.xsd"
    ID="12345" Name="_TestSpec">

    <PropertyClass Index="0">
    <Name>SomePropertyClass</Name>
    <PropertyClassName>_TestSubSpec1</PropertyClassName>
    </PropertyClass>

    <PropertyClassVec Index="1">
    <Name>VectorOfPropertyClasses</Name>
    <PropertyClassNames>
    <PropertyClassName>_TestSubSpec1</PropertyClassName>
    <PropertyClassName>_TestSubSpec1</PropertyClassName>
    <PropertyClassName>_TestSubSpec2</PropertyClassName>
    <PropertyClassName>_TestSubSpec3</PropertyClassName>
    </PropertyClassNames>
    <ReserveSize>100</ReserveSize>
    </PropertyClassVec>

    <SomeOtherTopLevelElement>
    <PropertyClassName>DontCatchThisOne</PropertyClassName>
    </SomeOtherTopLevelElement>

    <PropertyClassName>DontGrabThisOneEither</PropertyClassName>

    </PropertyClassSpec>


    Given that input, I'd want three xs:imports: one for _TestSubSpec1,
    _TestSubSpec2, and _TestSubSpec3.


    Here's the (not-quite-working) transform I have thus far (note: I'm
    using Saxon8B, so feel free to offer XSLT 2.0 solutions/suggestions,
    though v1.0 is fine, too):

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="2.0">

    <xsl:eek:utput method="xml" version="1.0" encoding="UTF-8"
    indent="yes"/>

    <!-- Consume any input we don't understand (no output generated) -->
    <xsl:template match="*"/>

    <!-- Root xs:schema element generation -->
    <xsl:template match="PropertyClassSpec">
    <xsl:element name="xs:schema">
    <xsl:attribute name="elementFormDefault" select="'qualified'"/>
    <xsl:attribute name="targetNamespace"
    select="concat('http://someDomain/', @Name)"/>
    <xsl:namespace name="xs"
    select="'http://www.w3.org/2001/XMLSchema'"/>

    <!-- I *think* this is an appropriate for-each selection...? -->
    <xsl:for-each
    select="PropertyClass/PropertyClassName |
    PropertyClassVec/PropertyClassNames/PropertyClassName">
    <xsl:sort order="ascending" select="text()"/>

    <!-- Try using a remainder-based comparison I found via a
    Google search. Maybe Muenchian would work, if I ever figure that out?
    -->
    <xsl:variable name="propertyClassName" select="text()"/>
    <xsl:variable name="remainder"
    select="following-sibling[text()=$propertyClassName]"/>
    <xsl:if test="not($remainder)">
    <xsl:element name="xs:import">
    <xsl:attribute name="namespace"
    select="concat('http://someDomain/',
    $propertyClassName)"/>
    <xsl:attribute name="schemaLocation"
    select="concat($propertyClassName, '.xsd')"/>
    </xsl:element>
    </xsl:if>
    </xsl:for-each>

    <!-- The schema, as aside from the namespace and imports
    determined above, has a single top-level element which is a sequence.
    All further template matching/process will generate elements for this
    sequence. -->
    <xsl:element name="xs:element">
    <xsl:attribute name="name" select="@Name"/>
    <xsl:element name="xs:complexType">
    <xsl:element name="xs:sequence">
    <xsl:apply-templates/>
    </xsl:element>
    </xsl:element>
    </xsl:element>
    </xsl:element>
    </xsl:template>

    <... other template matching and processing here, to generate child
    elements under the sequence element generated above ...>

    </xsl:stylesheet>

    Thank you for any suggestions/solutions you might be able to provide!

    Cheers,
    David
    , Oct 9, 2006
    #1
    1. Advertising

  2. roy axenov Guest

    wrote:
    > I have a unique-elements/sorting question (who doesn't?),
    > but haven't yet been able to get appropriate
    > template/select/for-each processing working. I don't
    > fully grok the Muenchian technique yet (still an XSLT
    > n00b), but I'm not sure that's the way to go anyway...
    >
    > What I'm trying to accomplish is generation of XML Schema
    > output from a given XML input, with "xs:import" elements
    > in the output with the "namespace" and "schemaLocation"
    > attributes corresponding to a unique set of text values
    > found in the input file. (I don't need assistance with
    > the required <xsl:element> output, as I have a solution
    > for that figured out. Just the appropriate
    > select/group/for-each processing, as the xs:import's must
    > be unique...)


    > Here is a sample input .XML file:


    [XML]

    > Here's the (not-quite-working) transform I have thus far
    > (note: I'm using Saxon8B, so feel free to offer XSLT 2.0
    > solutions/suggestions, though v1.0 is fine, too):


    You seem to have xmlns problems, among others. Anyway, try
    toying with the following, it just might do what you need:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet
    xmlns:f="http://someDomain/PropertyClassSpec"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="1.0">
    <xsl:eek:utput
    method="xml"
    version="1.0"
    encoding="UTF-8"/>
    <xsl:template match="/">
    <xsl:element name="xs:schema">
    <xsl:attribute
    name="elementFormDefault">qualified</xsl:attribute>
    <xsl:attribute
    name="targetNamespace"><xsl:value-of select="
    concat('http://someDomain/',@Name)
    "/></xsl:attribute>
    <xsl:apply-templates select="
    descendant::f:propertyClass/f:propertyClassName|
    descendant::f:propertyClassVec/f:propertyClassNames
    /f:propertyClassName">
    <xsl:sort order="ascending" select="text()"/>
    </xsl:apply-templates>
    </xsl:element>
    </xsl:template>
    <xsl:template
    match="//f:propertyClass/f:propertyClassName|
    //f:propertyClassVec/f:propertyClassNames
    /f:propertyClassName">
    <xsl:if
    test="generate-id(.)=
    generate-id((//f:propertyClass/f:propertyClassName|
    //f:propertyClassVec/f:propertyClassNames
    /f:propertyClassName)[text()=current()/text()][1])">
    <xsl:element name="xs:import">
    <xsl:attribute
    name="namespace"><xsl:value-of select="
    concat('http://someDomain/',text())
    "/></xsl:attribute>
    <xsl:attribute name="schemaLocation"><xsl:value-of
    select="concat(text(), '.xsd')"/></xsl:attribute>
    </xsl:element>
    </xsl:if>
    </xsl:template>
    </xsl:stylesheet>

    --
    roy axenov
    roy axenov, Oct 9, 2006
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kaleb Pederson

    OT? identifying elements of C++

    Kaleb Pederson, Feb 18, 2008, in forum: C++
    Replies:
    0
    Views:
    312
    Kaleb Pederson
    Feb 18, 2008
  2. Replies:
    4
    Views:
    251
  3. ToshiBoy
    Replies:
    6
    Views:
    831
    ToshiBoy
    Aug 12, 2008
  4. Neil
    Replies:
    4
    Views:
    157
  5. Token Type
    Replies:
    9
    Views:
    339
    Chris Angelico
    Sep 9, 2012
Loading...

Share This Page