如何使用Java中的节点属性值读取,更新和删除现有XML文件

时间:2012-05-28 13:49:39

标签: java xml regex xslt xpath

我正在尝试根据找到的值读取/更新/删除XML文件。

我有一个名称为123456.xm l的XML,格式如下。

<ps>
  <p n="359" u="/ae/arabic/plan_book/plan_and_book.aspx"/>
  <p n="277" u="/ae/english/plan_book/plan_and_book.aspx"/>
  <p n="410" u="/ao/english/plan_book/plan_and_book.aspx"/>
</ps>

现在,我在java中的新方法将获得Filepath(c://java/Files/12345.xml),n(277 - 将在文件中检查的值)和U(“/de/english/plan_book/plan_and_book.aspx”)。

我的java方法的逻辑如下,但实际上不知道如何写。

添加/添加方法逻辑:

  1. 打开文件c://java/Files/12345.xml
  2. 搜索所有节点并找到n的值的基础(277)。 277
  3. 只有一条记录
  4. 如果文件中存在此值,则不需要更新,否则在xml文件中添加新节点,例如,如果n的值为(777),因为该属性记录在文件中不存在,那么它会在文件中添加一条新记录(<p n="777" u="/ao/english/plan_book/plan_and_book.aspx"/>)。
  5. 将更新的XML保存在同一位置。
  6. 删除方法逻辑:

    1. 打开文件c://java/Files/12345.xml
    2. 搜索所有节点并根据n的值(277)查找。 277只会有一条记录。
    3. 如果节点属性“n”中存在此值,则它将从xml中删除该节点,否则无需更新。
    4. 将更新的XML保存在同一位置。
    5. 如果您与上述实施方案分享一些好的示例或链接,我们将不胜感激。

      感谢。

2 个答案:

答案 0 :(得分:3)

在XSLT中指定的这种处理通常比在命令式语言中更容易和更简单(不需要regEx)

下面的XSLT转换可以直接使用,也可以让我们知道如何用另一种语言实现相同的算法:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pAction" select="'delete'"/>
 <xsl:param name="pN" select="277"/>
 <xsl:param name="pU" select="'/de/english/plan_book/plan_and_book.aspx'"/>

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

 <xsl:template match="ps">
  <ps>
    <xsl:apply-templates select=
     "*[not($pAction = 'delete')]
     |
      *[$pAction = 'delete' and not(@n = $pN)]
     "/>
    <xsl:if test="$pAction = 'add' and not(p[@n = $pN])">
      <p n="{$pN}" u="{$pU}"/>
    </xsl:if>
  </ps>
 </xsl:template>

 <xsl:template match="p">
  <xsl:choose>
    <xsl:when test="not(@n = $pN)">
      <xsl:call-template name="identity"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:if test="not($pAction = 'delete')">
          <xsl:call-template name="identity"/>
      </xsl:if>
     </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<ps>
    <p n="359" u="/ae/arabic/plan_book/plan_and_book.aspx"/>
    <p n="277" u="/ae/english/plan_book/plan_and_book.aspx"/>
    <p n="410" u="/ao/english/plan_book/plan_and_book.aspx"/>
</ps>

产生了想要的正确结果:

<ps>
   <p n="359" u="/ae/arabic/plan_book/plan_and_book.aspx"/>
   <p n="410" u="/ao/english/plan_book/plan_and_book.aspx"/>
</ps>
参数$pAction更改为时

 <xsl:param name="pAction" select="''add'"/>

然后转换的结果是相同的XML文档(未更改)。

当参数为时:

 <xsl:param name="pAction" select="''add'"/>

,XML文档

<ps>
    <p n="359" u="/ae/arabic/plan_book/plan_and_book.aspx"/>
    <p n="410" u="/ao/english/plan_book/plan_and_book.aspx"/>
</ps>

然后结果是

<ps>
   <p n="359" u="/ae/arabic/plan_book/plan_and_book.aspx"/>
   <p n="410" u="/ao/english/plan_book/plan_and_book.aspx"/>
   <p n="277" u="/de/english/plan_book/plan_and_book.aspx"/>
</ps>

答案 1 :(得分:1)

当且仅当您的XML与您提供的示例一样简单时,您可以使用:

以下代码将迭代<p>元素的所有匹配项:

try {
    Pattern regex = Pattern.compile("(?is)(<p n=\"(\\d+)\" u=\"([^\"<>]+?)\"/>)");
    Matcher regexMatcher = regex.matcher(subjectString);
    while (regexMatcher.find()) {
        // matched text: regexMatcher.group()
        // match start: regexMatcher.start()
        // match end: regexMatcher.end()
    } 
} catch (PatternSyntaxException ex) {
    // Syntax error in the regular expression
}

要查找具有给定数字的特定节点(更好地说是字符串),请使用以下语法:

(?is)(<p n="#num_to_find#" )(u="[^"<>]+?"/>)

使用您选择的号码改变#num_to_find#。然后可以替换为:

$1#string_to_replacewith##

正则表达式解释

"(?is)" +                       // Match the remainder of the regex with the options: case insensitive (i); dot matches newline (s)
"(" +                           // Match the regular expression below and capture its match into backreference number 1
   "<p\\ n=\"#num_to_find#\"\\ " +     // Match the characters “<p n="#num_to_find#" ” literally
")" +
"(" +                           // Match the regular expression below and capture its match into backreference number 2
   "u=\"" +                         // Match the characters “u="” literally
   "[^\"<>]" +                      // Match a single character NOT present in the list “"<>”
      "+?" +                          // Between one and unlimited times, as few times as possible, expanding as needed (lazy)
   "\"/>" +                         // Match the characters “"/>” literally
")"  

希望这有帮助。