如何使用 x-path 仅迭代 xml 中的第一级节点?

发布于 2024-11-02 22:17:30 字数 3247 浏览 1 评论 0原文

我需要遍历 XML 文件。根节点有几个子节点,我需要按原样复制子节点或执行某些操作。为此,我正在开发 XSLT。下面是一个示例源 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>

在此 XML 中,我需要选择节点 authorclassCodeconfidentialityCodes,但我得到的是 text() 节点使用这段代码:

        <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>

到目前为止我的结果是这样的:

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>

有什么提示吗?谢谢。


编辑

抱歉,有一个错误(我删除了)。

实际上,我为什么使用 for-each 是因为我需要的文档与除了几个节点之外完全相同。在上面的示例中,最终输出应如下所示:

<?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>

编辑 2

我按照@Martin 的建议创建了此模板。但我仍然如何选择节点名称“作者”?

<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:choose>
            <xsl:when test="local-name()=author">
                    a
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>

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 test="local-name()=author">
                    a
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

望她远 2024-11-09 22:17:30

如果不知道 for-each 的上下文节点,就很难判断出了什么问题。我建议您忘记 for-each 并开始编写模板,例如,

<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>

如果您仍然遇到问题,请向我们展示您想要为您发布的示例输入创建什么样的输出,然后我们可以提供帮助正确的 XSLT 代码。

[编辑]
如果您想要的只是复制author元素的子节点之外的节点,那么两个模板就足够了:

<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>

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>
七秒鱼° 2024-11-09 22:17:30

该样式表:

<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>

输出:

<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>

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>
倥絔 2024-11-09 22:17:30

我按照建议创建了这个模板
由@马丁。但我仍然如何选择
节点名称“作者”??

答案

没有选择。相反,您可以使用与节点(在您的情况下是 author 元素,您希望对其进行不同的处理)完全匹配的更具体的模板来覆盖身份模板。只需“按原样”复制:

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

使用和覆盖身份规则是最基本、最强大的 XSLT 设计模式了解更多信息此处

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文