开发者

how to iterate only first level node in xml with x-path?

I need to iterate through an XML file. The root node has a few children and I need to either copy the child as is or to do something. So I'm working on an XSLT to do so. Here's a sample source XML:

<?xml version="1.0" encoding="utf-8"?>
<XDSDocumentEntry id="DOC01">
    <author authorRole="XDSITEST_DICOM_INSTANCE_PUBLISHER" authorPerson="XDSITEST">Author</author>
    <classCode displayName="Communication" codingScheme="Connect-a-thon classCodes">Communication</classCode>
    <confidentialityCode displayName="Celebrity" codingScheme="Connect-a-thon confidentialityCodes">
</XDSDocumentEntry>

In this XML I need to select nodes author, classCode and confidentialityCodes but I'm getting the text() nodes with this code:

        <xsl:for-each select="node()"><!--<xsl:copy-of select="."/>-->
            <!--<xsl:value-of select="local-name()"/>-->
            <xsl:choose>
                <xsl:when test="author">
                    do something
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>

My result so far is this:

author<author authorRole="XDSITEST_DICOM_INSTANCE_PUBLISHER" authorPerson="XDSITEST"
       authorInstitution="Some institution"/>
classCode<classCode displayName="Communication" codingScheme="Connect-a-thon classCodes">Communication</classCode>
confidentialityCode<confidentialityCode displayName="Celebrity" codingScheme="Connect-a-thon confidentialityCodes">
C</confidentialityCode>

Any hint? Thx.


EDIT

Sorry, had an error (I removed ).

Actually, why am I using the for-each is because I need the document exactly as it was except for a few nodes. In the example above the final output should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<XDSDocumentEntry>
    <author authorRole="XDSITEST_DICOM_INSTANCE_PUBLISHER" authorPerson="XDSITEST"
           authorInstitution="Some institution"/>
    <author>
        <authorInstitution>
            <organizationName>Some institution</organizationName>
        </authorInstitution>
        <authorRole>XDSITEST_DICOM_INSTANCE_PUBLISHER</authorRole>
        <authorPerson>
            <assigningAuthorityName>XDSITEST</assigningAuthorityName>
        </authorPerson>
    </author>
    <classCode displayName="Communication" codingScheme="Connect-a-thon classCodes">Communication</classCode>
    <confidentialityCode displayName="Celebrity" codingScheme="Connect-a-thon confidentialityCodes">
    C</confidentialityCode>
</XDSDocumentEntry>

EDIT 2

I created this template as suggested by @Martin. But still how do I select the node name 'author'??

<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:choose>
            <xsl:when t开发者_如何学Cest="local-name()=author">
                    a
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>


It is hard to tell what goes wrong without knowing the context node of your for-each. I would suggest you forget about for-each and instead start writing templates e.g.

<xsl:template match="XDSDocumentEntry/*">
  <!-- output here what you want to output for child elements of XDSDocumentEntry -->
</xsl:template>

<xsl:template match="XDSDocumentEntry/author">
  <!-- put needed special treatement of author element here -->
</xsl:template>

If you still have problems then show us what kind of output you want to create for the sample input you posted, then we can help with the proper XSLT code.

[edit] If all you want is copying nodes besides the child nodes of the author element then two templates suffice:

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="XDSDocumentEntry/author">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
  </xsl:copy>
</xsl:template>


This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="author/node()"/>
    <xsl:template match="author">
        <xsl:call-template name="identity"/>
        <xsl:copy>
            <xsl:apply-templates select="@*" mode="element"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="@*" mode="element">
        <xsl:element name="{name()}">
            <xsl:apply-templates select="." mode="value"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="author/@authorPerson" mode="value">
        <assigningAuthorityName>
            <xsl:value-of select="."/>
        </assigningAuthorityName>
    </xsl:template>
</xsl:stylesheet>

Output:

<XDSDocumentEntry id="DOC01">
    <author authorRole="XDSITEST_DICOM_INSTANCE_PUBLISHER" authorPerson="XDSITEST"></author>
    <author>
        <authorRole>XDSITEST_DICOM_INSTANCE_PUBLISHER</authorRole>
        <authorPerson>
            <assigningAuthorityName>XDSITEST</assigningAuthorityName>
        </authorPerson>
    </author>
    <classCode displayName="Communication" codingScheme="Connect-a-thon classCodes">Communication</classCode>
    <confidentialityCode displayName="Celebrity" codingScheme="Connect-a-thon confidentialityCodes"></confidentialityCode>
</XDSDocumentEntry>


I created this template as suggested by @Martin. But still how do I select the node name 'author'??

Answer:

You do not select. Instead, you override the identity template with a more specific template that matches exactly the node(s) (in your case the author element, for which you want a different processing than simply copy "as-is":

<xsl:template match="author">
  <!-- Put your specific code here -->
</xsl:template>

Using and overriding the identity rule is the most fundamental and powerful XSLT design pattern. Read more about it here.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜